Java Forum / General / October 2005
getActualMaximum of Calendar.WEEK_OF_MONTH confusion
pit.grinja@gmx.de - 08 Oct 2005 16:05 GMT Hi there, For a custom dialog that will allow users to select a date I wrote a JTable that displays the days of one complete month. The JTable gets an instance of GregorianCalendar as parameter. The table has seven columns, first header is "Sun",last header is "Sat". To correctly determine the number of rows, I wanted to use the method getActualMaximum(Calendar.WEEK_OF_MONTH). However, for some months, the return value is less than I would expect. Here is a sample program: import java.util.*;
public class DatePrinter{ private GregorianCalendar cal; private final String[] WEEKDAYS = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; public DatePrinter(){ this.cal = new GregorianCalendar(); cal.setFirstDayOfWeek(Calendar.SUNDAY); int year = this.cal.get(Calendar.YEAR); int month = this.cal.get(Calendar.MONTH); int firstWeekdayOfMonth = (new GregorianCalendar(year,month,1).get(Calendar.DAY_OF_WEEK)); System.out.println("First Day of Month: "+WEEKDAYS[firstWeekdayOfMonth-1]); System.out.println("Day: "+this.cal.get(Calendar.DAY_OF_MONTH)); System.out.println("Month: "+(this.cal.get(Calendar.MONTH)+1)); System.out.println("Year: "+this.cal.get(Calendar.YEAR)); System.out.println("Weeks in actual month: "+this.cal.getActualMaximum(Calendar.WEEK_OF_MONTH)); System.out.println("Number of days in actual month: "+this.cal.getActualMaximum(Calendar.DAY_OF_MONTH)); } public static void main(String[] ARGS){ DatePrinter dp = new DatePrinter(); } } //end of code For october, I would expect a value of 6 for this.cal.getActualMaximum(Calendar.WEEK_OF_MONTH): first week: just the saturday of october 1st, 2nd week: oct 2-8, 3rd week: 9-15,... 6th week: 30-31. But the return value is 5. For january, april, july,september and december, i also get wrong (i.e. to small) values. Is this a flaw in Java? I am using 1.4.2_08b03 on Win2000. Or is my thinking wrong? Many thanks for any pointers
Piet
Roedy Green - 09 Oct 2005 05:24 GMT >For october, I would expect a value of 6 for >this.cal.getActualMaximum(Calendar.WEEK_OF_MONTH): first week: just the [quoted text clipped - 4 lines] >thinking wrong? >Many thanks for any pointers Date and Calendar are born to surprise. You have to read the JavaDoc very carefully. There are many gotchas. I have documented some at http://mindprod.com/jgloss/gotchas.html#DATE and http://mindprod.com/jgloss/calendar.html
If you just want to get the job done, you can use the BigDate methods instead which behave more as you might expect. See http://mindprod.com/products1..html#BIGDATE
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
pit.grinja@gmx.de - 09 Oct 2005 11:43 GMT > >For october, I would expect a value of 6 for > >this.cal.getActualMaximum(Calendar.WEEK_OF_MONTH): first week: just the > >saturday of october 1st, 2nd week: oct 2-8, 3rd week: 9-15,... 6th > >week: 30-31. But the return value is 5. For january, april, > >july,september and december, i also get wrong (i.e. to small) values.
> Date and Calendar are born to surprise. You have to read the JavaDoc > very carefully. There are many gotchas. I have documented some at > http://mindprod.com/jgloss/gotchas.html#DATE and > http://mindprod.com/jgloss/calendar.html Many thanks for the links. Now I know where to look when the next strange things happen.
> If you just want to get the job done, you can use the BigDate methods > instead which behave more as you might expect. See > http://mindprod.com/products1..html#BIGDATE Since all I wanted to achieve is to get the right number of rows in my MonthCalendarJTable, I simply calculated the value on my own. Here is the solution. It assumes that your week starts on sunday: int firstWeekdayOfMonth = (new GregorianCalendar(year,month,1).get(Calendar.DAY_OF_WEEK)); int correctNumberOfWeeks = (int)((firstWeekdayOfMonth+this.cal.getActualMaximum(Calendar.DAY_OF_MONTH)+5)/7)); That formula handles july 2005 correctly (last day of this month is sunday, thus the last row has only one active cell) and also december 2005 (last day is saturday, so the last row is full). Best wishes Piet
P.Hill - 10 Oct 2005 23:48 GMT >>>For october, I would expect a value of 6 for >>>this.cal.getActualMaximum(Calendar.WEEK_OF_MONTH): first week: just the [quoted text clipped - 6 lines] >>http://mindprod.com/jgloss/gotchas.html#DATE and >>http://mindprod.com/jgloss/calendar.html AFAIK, None of which actually answer the question of the OP.
> Since all I wanted to achieve is to get the right number of rows in my > MonthCalendarJTable, I simply calculated the value on my own. Hi Piet,
What's up with the value you calculated? Despite Roedy's assumption that no value from Calendar or Date could possibly be right, running your code under 1.4.2_08 gave me the result you wanted of 6 not 5 which you reported for the number of weeks in the month.
-Paul
pit.grinja@gmx.de - 12 Oct 2005 21:19 GMT Paul,
> >>>For october, I would expect a value of 6 for > >>>this.cal.getActualMaximum(Calendar.WEEK_OF_MONTH): first week: just the > >>>saturday of october 1st, 2nd week: oct 2-8, 3rd week: 9-15,... 6th > >>>week: 30-31. But the return value is 5. For january, april, > >>>july,september and december, i also get wrong (i.e. to small) values.
> > Since all I wanted to achieve is to get the right number of rows in my > > MonthCalendarJTable, I simply calculated the value on my own.
> What's up with the value you calculated? Despite Roedy's assumption > that no value from Calendar or Date could possibly be right, running > your code under 1.4.2_08 gave me the result you wanted of 6 not 5 > which you reported for the number of weeks in the month. With "your code" you mean my "DatePrinter" class, right? I just tried that again and got ... five weeks in october. Have you tried other months? When you have some time to spend you can try the following:
import java.util.*;
public class DatePrinter{ private GregorianCalendar cal; private final String[] WEEKDAYS = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; public DatePrinter(){ this.cal = new GregorianCalendar(); cal.setFirstDayOfWeek(Calendar.SUNDAY); int year = this.cal.get(Calendar.YEAR); System.out.println("Month:\tWeeks\tWeeks,corr"); for (int i =0;i<12;i++){ this.cal.set(Calendar.MONTH,i); int firstWeekdayOfMonth = (new GregorianCalendar(year,i,1).get(Calendar.DAY_OF_WEEK)); int weeks = this.cal.getActualMaximum(Calendar.WEEK_OF_MONTH); int weeks_corr = (int)((firstWeekdayOfMonth+this.cal.getActualMaximum(Calendar.DAY_OF_MONTH)+5)/7); System.out.println((i+1)+"\t"+weeks+"\t"+weeks_corr); } } public static void main(String[] ARGS){ DatePrinter dp = new DatePrinter(); } }
On my system, I get the following triples: 1-5-6;2-5-5;3-5-5;4-4-5;5-5-5;6-5-5;7-5-6;8-5-5;9-4-5;10-5-6;11-5-5;12-4-5. As already posted, I sometimes get one day less than I expect. Anyway, that doesn´t bother me any more. Instead of calculating the number of rows for my MonthCalendarTable by whatAlgorithmEver, I fixed it to 6. Now I have one or even two completely empty rows in my table, but that´s fine. Best wishes Piet
P.Hill - 13 Oct 2005 07:10 GMT > Paul, > On my system, I get the following triples: Yours 1-5-6;2-5-5;3-5-5;4-4-5;5-5-5;6-5-5;7-5-6;8-5-5;9-4-5;10-5-6;11-5-5;12-4-5. Mine 1-6-6;2-5-5;3-5-5;4-5-5;5-5-5;6-5-5;7-6-6;8-5-5;9-5-5;10-6-6;11-5-5;12-5-5; * * * * *
I got this by changing your coded to end with: System.out.print((i+1)+"-"+weeks+"-"+weeks_corr+";"); } System.out.println(); }
I even tried using one calendar for all calculations (changing the the second occurance of new Calendar()), and setting the one cal's timezone to CET -- assuming your are in Central European Time -- but got the good results. What IS your TZ?
Placing the line: System.out.println(cal.getTimeZone().getDisplayName()); in your code (after I made sure to override the TZ) results in: Central European Time
I think we only differ in OS and TZ and the time of day we run the code, but once in the VM I would think the OS would reduce a difference in TZ. Do you get different results if you set the hours, minutes and seconds to 0?
-Paul
Roedy Green - 12 Oct 2005 23:48 GMT >Since all I wanted to achieve is to get the right number of rows in my >MonthCalendarJTable, I simply calculated the value on my own. Here is >the solution. here is some code to generate an HTML calendar
package com.mindprod.lisa;
import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter;
import com.mindprod.business.BigDate;
/** * produces an HTML table calendar for any month * suitable as a skeleton for a coming events schedule. * put yyyy mm on command line. * * Requires BigDate from * http://mindprod.com/products.html#BIGDATE * * May be freely used for any purpose but military * * @author Roedy Green * @author copyright (c) 2003-2005 Roedy Green, Canadian Mind Products * @version 1.0 */ public class CalMaker {
/** * Months of the year */ private static final String[] monthNames = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December",};
/** * days of the week 3 letter abbreviations in English. Index Sunday = 0. */ private static final String[] shortDayName = { "sun" , "mon", "tue", "wed" , "thu", "fri", "sat"};
/** * outputs cal.html in current directory with an HTML table for that month. * * @param args year month, e.g. 2003 11 * @exception IOException */ public static void main ( String[] args ) throws IOException { System.out.println("Results appear in cal.html" );
int year = Integer.parseInt( args [0] ); int month = Integer.parseInt( args [1] ); PrintWriter out = new PrintWriter ( new FileWriter( "cal.html" )); out.println ( "<table width=\"620\" border=\"1\" cellspacing=\"1\" bordercolor=\"#808080\" cellpadding=\"7\">" );
// header out.println ( "<tr><th colspan=\"7\">Coming events for " + monthNames[ month-1] + " " + year + "</th></tr>" );
// label days of the week out.println( "<tr>" ); for ( int i=0; i<7; i++ ) { out.println( "<th>" + shortDayName[ i ] + "</th>" ); } out.println( "</tr>" );
// dummy boxes before the month starts, possibly none. BigDate firstOfMonth = new BigDate ( year, month, 1 ); int dummystarts = firstOfMonth.getDayOfWeek(); for ( int i=0; i<dummystarts; i++ ) { if ( i== 0 ) { out.println("<tr>"); } out.println("<td> </td>"); }
// label days of the month int daysInMonth = BigDate.daysInMonth( month, year ); for ( int day=1; day<=daysInMonth; day++ ) { BigDate d = new BigDate ( year, month, day ); if ( d.getDayOfWeek() == 0 ) { out.println("<tr>"); } out.println( "<td width=\"90\"><span class=\"daynumber\">" + day + "</span> </td>"); if ( d.getDayOfWeek() == 6 ) { out.println("</tr>"); } }
// dummy boxes after the month ends, possibly none. BigDate lastOfMonth = new BigDate ( year, month, daysInMonth ); int dummyStops = 6 - lastOfMonth.getDayOfWeek(); for ( int i=0; i<dummyStops; i++ ) { out.println("<td> </td>"); if ( i == dummyStops-1 ) { out.println("</tr>"); } }
out.println ( "</table>" ); out.close();
} }
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|