Bug in java.util.Calendar's set() after add()'ing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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< ===



[Index of Archives]     [Linux Kernel]     [Linux Cryptography]     [Fedora]     [Fedora Directory]     [Red Hat Development]

  Powered by Linux