Hi there,
After having updated Calendar and GregorianCalendar from svn-trunk to
fix an old DST bug, I did some testing and found a bug in Calendar.
The bug occurs when using the Calendar's #set(,) if time is set and
fields are not ( isTimeSet = true; and areFieldsSet = false; )
This happens e.g. after doing an #add(,) for the field Calendar.DAY_OF_YEAR.
However, this bug can be worked around by get'ing a field inbetween the
add(,) and the set(,) [the #get() triggers a recalculation of the fields
invalidated by the add(,)].
An example source illustrating this is shown below, and the output here:
=== 8< 8< 8< ===
WITHOUT getting before setting:
millis till tomorrow: 86400040
millis till tomorrow: -816
WITH getting before setting:
millis till tomorrow: 86400040
millis till tomorrow: 86399184
=== 8< 8< 8< ===
The second line in each output-pair should be (almost) identical to the
first, but without the #get() inbetween it's not.
I reckon the solution is to put in a call to #complete() in Calendar's
#set(,):
=== 8< 8< 8< ===
public void set(int field, int value)
{
// We need completing everything before we can proceed.
// Fields may be invalid after doing an #add(,):
--> complete();
if (isTimeSet)
=== 8< 8< 8< ===
One could put it in Gregorian's #add(,), as well, but that could result
in unnecessarily many complete()-calls if doing suceeding add(,)'s.
I hope you agree, for I have patched mine like that ;-)
BR,
Martin Egholm
=== 8< 8< 8< ===
import java.util.Calendar;
public final class CalendarAndAddingAndSetting
{
public static void main(String[] args)
{
Calendar now = Calendar.getInstance();
{
System.out.println("WITHOUT getting before setting:");
Calendar tomorrowAtSameTime = Calendar.getInstance();
tomorrowAtSameTime.add(Calendar.HOUR_OF_DAY, 24);
System.out.println("millis till tomorrow: "
+ (tomorrowAtSameTime.getTimeInMillis() -
now.getTimeInMillis()));
tomorrowAtSameTime.set(Calendar.MILLISECOND, 0);
System.out.println("millis till tomorrow: "
+ (tomorrowAtSameTime.getTimeInMillis() -
now.getTimeInMillis()));
} // block
System.out.println();
{
System.out.println("WITH getting before setting:");
Calendar tomorrowAtSameTime = Calendar.getInstance();
tomorrowAtSameTime.add(Calendar.HOUR_OF_DAY, 24);
System.out.println("millis till tomorrow: "
+ (tomorrowAtSameTime.getTimeInMillis() -
now.getTimeInMillis()));
tomorrowAtSameTime.get(Calendar.DAY_OF_MONTH);
tomorrowAtSameTime.set(Calendar.MILLISECOND, 0);
System.out.println("millis till tomorrow: "
+ (tomorrowAtSameTime.getTimeInMillis() -
now.getTimeInMillis()));
} // block
} // main
} // CalendarAndAddingAndSetting
=== 8< 8< 8< ===