Java Chatter and Random Nagging

Tuesday, May 15, 2007

Java Calendar Bug ?! Setting before Getting

Saturday Fever
This one kept me puzzling for quite a while. I was trying to loop over every saturday of the year to fill in a weekend for my Human Resource Application. I had a tested convenience method that returned the first day of a given year and my first try was to use this method and afterwards set the day of week to saturday. The extracted bugcode looks like this :

public class BugWhileLookingForTheFirstSaturdayOfYear {
public static void main(String[] args) {
strange();
strangeFixed();
}

private static void strange() {
Calendar calendar = firstDayOf2007();

calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
System.out.println(calendar.getTime());
}

private static void strangeFixed() {
Calendar calendar = firstDayOf2007();

//Adding this line solves it !!
calendar.get(Calendar.YEAR);

calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
System.out.println(calendar.getTime());

}

private static Calendar firstDayOf2007() {
Calendar calendar = Calendar.getInstance();
calendar.set(2007, Calendar.JANUARY, 1, 0, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}
}

This generates the following lines :

Sat Jan 20 00:00:00 CET 2007
Sat Jan 06 00:00:00 CET 2007


Strange, right ? But apparently this behavior is "Works As Designed" ! When digging into the java.util.Calendar class, things become a lot more clear. Apparently, simply using set(int, int) for setting a certain property does not immediately set the time of the calendar object to the given value. It only computes this value when calling the add(int, int) or get(int) method. Thus setting the DAY_OF_WEEK cancels out our setting of the DAY_OF_MONTH in calendar.set(2007, Calendar.JANUARY, 1, 0, 0).

You can figure out that the reason why we get the wrong value of Jan 20th is because of the fact that today is the 16th of May. The next saturday counting from the 16th of January is indeed the 20th of January. The problem can easily be solved by calling a get(int) before using set(int) again, but it took me a complete hour to figure out this Calendar headache.

Related bug (and Closed Correctly) : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6212052

0 Comments:

Post a Comment

<< Home