Output quality
Your output for February 2016 looks like this:
<table style="width:100%;border-collapse: collapse;border: thin green solid;background-color:#E0F0FF;">
<tr style="width:100%;border: thin black solid;">
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center"> S</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center"> M</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center"> T</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center"> W</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center"> T</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center"> F</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center"> S</td>
</tr>
<tr style="width:100%;border: thin black solid;height:100px">
<td style="width:12%;border: none;margin: auto;text-align:center"> </td>
<td style="width:12%;border: none;margin: auto;text-align:center"> </td>
<td style="width:12%;border: none;margin: auto;text-align:center"> </td>
<td style="width:12%;border: none;margin: auto;text-align:center"> </td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">1</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">2</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">3</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
</tr>
<tr style="width:100%;border: thin black solid;height:100px">
</tr>
<tr style="width:100%;border: thin black solid;height:100px">
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">4</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">5</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">6</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">7</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">8</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">9</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">10</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
</tr>
<tr style="width:100%;border: thin black solid;height:100px">
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">11</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">12</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">13</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">14</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">15</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">16</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">17</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
</tr>
<tr style="width:100%;border: thin black solid;height:100px">
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">18</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">19</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">20</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">21</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">22</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">23</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">24</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
</tr>
<tr style="width:100%;border: thin black solid;height:100px">
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">25</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">26</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">27</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">28</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
<td style="width:12%;border: thin black solid;border-collapse: collapse;margin: auto;text-align:center;">
<div style="height: 10%;float:right;width:12%; color: #0033CC; background-color:lightblue;font-size: larger;border: thin black solid;">29</div>
<div style="width: 100%;text-align: left;">
<ul>
</ul>
</div>
</td>
</tr>
</table>
Note that there is an extra <tr>
tag after Feb 3, due to the monthHTML += "</tr><tr>"
before //get sentinal for loop for rest of calendar
.
The bigger issue is that writing style
attributes everywhere, especially repetitive ones, is considered poor practice: styling should be done using stylesheets for compactness and maintainability. (The only exception is if you are writing HTML to be embedded in e-mail, because some e-mail clients have primitive HTML renderers.)
Did you mean for the numbers to appear in the upper-right corner instead of being centered vertically on the right? If so, you'll want a vertical-align: top
rule. Furthermore, since the numbers are float
ed, you may want to put a clear: right
rule on the <ul>
elements so that they start consistently below the number. Avoid hard-coding a height and width for the number box that won't scale with the text size.
I would also put a <caption>
on the table as its title. If you don't want to see it in the output, just put a display: none
rule in the CSS to suppress it.
The output should look more like this:
table.calmonth {
width: 100%;
border-collapse: collapse;
border: thin green solid;
background-color: #E0F0FF;
}
table.calmonth td {
height: 100px;
vertical-align: top;
}
table.calmonth th, table.calmonth td {
width: 12%;
border: thin black solid;
}
table.calmonth th {
text-align: center;
}
table.calmonth td.blank {
border-width: 0;
}
table.calmonth div.daynum {
float: right;
width: 1.5em;
text-align: center;
color: #03C;
background-color: lightblue;
font-size: larger;
border: thin solid black;
}
table.calmonth td > ul {
clear: right;
}
<table class="calmonth">
<caption>February</caption>
<tr><th>S</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th></tr>
<tr>
<td class="blank"></td><td><div class="daynum">1</div><ul></ul></td><td><div class="daynum">2</div><ul></ul></td><td><div class="daynum">3</div><ul></ul></td><td><div class="daynum">4</div><ul></ul></td><td><div class="daynum">5</div><ul></ul></td><td><div class="daynum">6</div><ul></ul></td></tr>
<tr>
<td><div class="daynum">7</div><ul></ul></td><td><div class="daynum">8</div><ul></ul></td><td><div class="daynum">9</div><ul></ul></td><td><div class="daynum">10</div><ul></ul></td><td><div class="daynum">11</div><ul></ul></td><td><div class="daynum">12</div><ul></ul></td><td><div class="daynum">13</div><ul></ul></td></tr>
<tr>
<td><div class="daynum">14</div><ul></ul></td><td><div class="daynum">15</div><ul></ul></td><td><div class="daynum">16</div><ul></ul></td><td><div class="daynum">17</div><ul></ul></td><td><div class="daynum">18</div><ul></ul></td><td><div class="daynum">19</div><ul></ul></td><td><div class="daynum">20</div><ul></ul></td></tr>
<tr>
<td><div class="daynum">21</div><ul></ul></td><td><div class="daynum">22</div><ul></ul></td><td><div class="daynum">23</div><ul></ul></td><td><div class="daynum">24</div><ul></ul></td><td><div class="daynum">25</div><ul></ul></td><td><div class="daynum">26</div><ul></ul></td><td><div class="daynum">27</div><ul></ul></td></tr>
<tr>
<td><div class="daynum">28</div><ul></ul></td><td><div class="daynum">29</div><ul></ul></td></tr>
</table>
Code quality
Your createCalendar()
method is hard-coded to send its output to a certain file. For flexibility, I would split it up into two: one method responsible for generating the HTML, and another for writing it to the appropriate file. Someday you might want to have the output directly written out on-the-fly from your Servlet engine to the client. Or, you could write a unit test that doesn't touch the filesystem.
I suggest renaming the method to createHtmlMonthCalendar
to be precise.
If you don't know what to do with an exception, declare the exception and let it propagate. Here, your jButton1ActionPerformed()
should catch it and display an alert box.
Repeated string concatenation is highly discouraged for performance scalability. Usually, a StringBuilder
would be better. In this case, since you intend to write the output out, I recommend a Writer
.
The //loop through rest of first week
is partly to blame for the extra <tr>
bug. In any case, copy-and-pasted code is undesirable. I suggest that instead of counting from 1 to the end of the month, you iterate using a GregorianCalendar
object instead. Advantages are:
- You can switch the output based on whether the current date is in the right month.
- You can query the object for the day of the week, which makes the code more expressive.
- You can pass the date as a callback to fetch the list of events for that day.
- It's robust in odd situations like the Julian-to-Gregorian transition.
To obtain the filename, you can take full advantage of SimpleDateFormat
instead of performing string concatenation. For cross-platform compatibility, use System.getProperty("java.io.tmpdir")
instead of hard-coding "C:/temp/"
.
Avoid declaring FileWriter
far away from its point of use, and avoid setting it to null
for no good reason. Also, use a try-with-resources block so that you don't need to close()
it manually.
Suggested solution
public void createHtmlMonthCalendar(GregorianCalendar month)
throws IOException {
Format pathFmt = new SimpleDateFormat("MMMYYYY'.html'");
File path = new File(System.getProperty("java.io.tmpdir"),
pathFmt.format(month.getTime()));
try (FileWriter fw = new FileWriter(path)) {
createHtmlMonthCalendar(month, fw);
}
}
public void createHtmlMonthCalendar(GregorianCalendar month, Writer out)
throws IOException {
month = (GregorianCalendar)month.clone();
month.set(Calendar.DATE, 1);
GregorianCalendar nextMonth = (GregorianCalendar)month.clone();
nextMonth.add(Calendar.MONTH, 1);
Format titleFmt = new SimpleDateFormat("MMMM");
out.write("<table class=\"calmonth\">\n<caption>");
out.write(titleFmt.format(month.getTime())); // should be HTML-escaped
out.write("</caption>\n");
// Rewind to the start of the week, then rewind another week as
// a hack to get the headings
GregorianCalendar d = (GregorianCalendar)month.clone();
d.add(Calendar.DATE,
month.getFirstDayOfWeek() - month.get(Calendar.DAY_OF_WEEK) - 7);
// week names header
SimpleDateFormat weekAbbrev = new SimpleDateFormat("E");
out.write("<tr>");
for (int i = 0; i < 7; i++, d.add(Calendar.DATE, 1)) {
out.write("<th>");
out.write(weekAbbrev.format(d.getTime()).charAt(0));
out.write("</th>");
}
// hack: the TR for the header will be immediately closed below
assert d.get(Calendar.DAY_OF_WEEK) == month.getFirstDayOfWeek();
// body
SimpleDateFormat dayNum = new SimpleDateFormat("d");
for (; d.before(nextMonth); d.add(Calendar.DATE, 1)) {
if (d.get(Calendar.DAY_OF_WEEK) == month.getFirstDayOfWeek()) {
out.write("</tr>\n<tr>\n");
}
if (d.get(Calendar.MONTH) != month.get(Calendar.MONTH)) {
out.write("<td class=\"blank\"></td>");
} else {
out.write("<td><div class=\"daynum\">");
out.write(dayNum.format(d.getTime()));
out.write("</div>");
String events = getDayContents((GregorianCalendar)d.clone());
if (events != null) {
out.write(events);
}
out.write("</td>");
}
}
out.write("</tr>\n</table>\n");
out.flush();
}
private String getDayContents(GregorianCalendar day) {
// stub, to be filled in
return "<ul></ul>";
}
Note that I have made a half-hearted attempt at internationalization. When executed in a European locale, this code can generate calendars that start with Monday. (On the other hand, some details are still wrong. For example, in a Chinese locale, the days of the week should be 日、一、二、三、四、etc., but this code outputs 星、星、星、星、星、etc.)