Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8017130

Calendar.clone does not update internal values of the calendar

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 7
    • core-libs

      FULL PRODUCT VERSION :
      java version "1.7.0_04"
      Java(TM) SE Runtime Environment (build 1.7.0_04-b22)
      Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      Calendar.clone() does not internally recalculate the calendar. Two clones in a row result in an wrong result.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      import java.text.DateFormat;
      import java.util.Calendar;
      import java.util.Locale;
      import java.util.TimeZone;

      /**
       * Calendar Clone bug. Execute with -ea!
       */
      public class CalendarBug
      {
          private static final DateFormat DATE_FORMAT = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);

          public static void main(String[] args)
          {
              try
              {
                  assert false;
                  throw new IllegalStateException("Please enabled assertions using the -ea switch");
              }
              catch (AssertionError e)
              {
                  // ok, assertions are on
              }

              Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"), Locale.US);

              // define some date, e.g. the 1st December (day 336 of year)
              calendar.set(2012, 11, 1, 22, 26);

              // clone the calendar
              Calendar first = (Calendar) calendar.clone();

              // set the day of the year to the day before, e.g. 30th November
              first.set(Calendar.DAY_OF_YEAR, 335);

              // if the first calendar is used, internal values are calculated
              // if you uncomment the following line, the assertions are correct
              // first.getTime();

              // clone another time
              Calendar second = (Calendar) first.clone();

              // update to the first of day
              second.set(Calendar.DAY_OF_MONTH, 1);

              assert "12/1/12".equals(DATE_FORMAT.format(calendar.getTime())) : "Expected 12/1/12 but got "
                  + DATE_FORMAT.format(calendar.getTime());
              assert "11/30/12".equals(DATE_FORMAT.format(first.getTime())) : "Expected 11/30/12 but got "
                  + DATE_FORMAT.format(first.getTime());
              assert "11/1/12".equals(DATE_FORMAT.format(second.getTime())) : "Expected 11/1/12 but got "
                  + DATE_FORMAT.format(second.getTime());
          }
      }


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The code should not throw assertions or exceptions. Calendar.clone() should internally recalculate the calendar prior of cloning.
      ACTUAL -
      The code throws following assertion: Exception in thread "main" java.lang.AssertionError: Expected 11/1/12 but got 12/1/12
      at CalendarBug.main(CalendarBug.java:51)
      Calendar.clone() does not update internal values of the calendar.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.text.DateFormat;
      import java.util.Calendar;
      import java.util.Locale;
      import java.util.TimeZone;

      /**
       * Calendar Clone bug. Execute with -ea!
       */
      public class CalendarBug
      {
          private static final DateFormat DATE_FORMAT = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);

          public static void main(String[] args)
          {
              try
              {
                  assert false;
                  throw new IllegalStateException("Please enabled assertions using the -ea switch");
              }
              catch (AssertionError e)
              {
                  // ok, assertions are on
              }

              Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"), Locale.US);

              // define some date, e.g. the 1st December (day 336 of year)
              calendar.set(2012, 11, 1, 22, 26);

              // clone the calendar
              Calendar first = (Calendar) calendar.clone();

              // set the day of the year to the day before, e.g. 30th November
              first.set(Calendar.DAY_OF_YEAR, 335);

              // if the first calendar is used, internal values are calculated
              // if you uncomment the following line, the assertions are correct
              // first.getTime();

              // clone another time
              Calendar second = (Calendar) first.clone();

              // update to the first of day
              second.set(Calendar.DAY_OF_MONTH, 1);

              assert "12/1/12".equals(DATE_FORMAT.format(calendar.getTime())) : "Expected 12/1/12 but got "
                  + DATE_FORMAT.format(calendar.getTime());
              assert "11/30/12".equals(DATE_FORMAT.format(first.getTime())) : "Expected 11/30/12 but got "
                  + DATE_FORMAT.format(first.getTime());
              assert "11/1/12".equals(DATE_FORMAT.format(second.getTime())) : "Expected 11/1/12 but got "
                  + DATE_FORMAT.format(second.getTime());
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Call e.g. calendar.getTime() after cloning

            okutsu Masayoshi Okutsu
            peytoia Yuka Kamiya (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: