getActualMaximum of Calendar.WEEK_OF_MONTH confusion

P

pit.grinja

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
 
R

Roedy Green

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

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
 
P

pit.grinja

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

P.Hill

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
 
P

pit.grinja

Paul,
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
 
R

Roedy Green

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>&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;</td>");
if ( i == dummyStops-1 )
{
out.println("</tr>");
}
}

out.println ( "</table>" );
out.close();

}
}
 
P

P.Hill

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top