Name: gm110360 Date: 03/16/2004 FULL PRODUCT VERSION : java version "1.4.2_04" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05) Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode) FULL OS VERSION : Linux standa 2.4.18 #15 Thu Mar 13 16:23:20 CET 2003 i686 Intel(R) Celeron(R) CPU 1.70GHz GenuineIntel GNU/Linux EXTRA RELEVANT SYSTEM CONFIGURATION : This bug is on all the platforms A DESCRIPTION OF THE PROBLEM : In GregorianCalendar's instance having its date set to the 29th of February 2000 (or any other leap-year) and rolling year to a non-leap year by call to roll(Calendar.YEAR, -1), the resulted date is 1st of March 1999 instead of 28th of February 1999. This means that rolling of the year in this case affects other fields, which doesn't fit the way it should be. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Save included source code to a file named BugTest.java, compile and run. Check system output for the results. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - Tue Feb 29 20:34:45 CET 2000 Sun Feb 28 20:34:45 CET 1999 ACTUAL - Tue Feb 29 20:34:45 CET 2000 Mon Mar 01 20:34:45 CET 1999 REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.util.*; public class BugTest { public BugTest() { } public static void main(String[] args) { GregorianCalendar cal = new GregorianCalendar(); cal.set(Calendar.YEAR, 2000); cal.set(Calendar.MONTH, Calendar.FEBRUARY); cal.set(Calendar.DAY_OF_MONTH, 29); System.out.println(cal.getTime()); cal.roll(Calendar.YEAR, -1); System.out.println(cal.getTime()); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : In GregorianCalendar.java, about line 773, replace the code switch (field) { case ERA: case YEAR: case AM_PM: case MINUTE: case SECOND: case MILLISECOND: // These fields are handled simply, since they have fixed minima // and maxima. The field DAY_OF_MONTH is almost as simple. Other // fields are complicated, since the range within they must roll // varies depending on the date. break; by code switch (field) { case ERA: case AM_PM: case MINUTE: case SECOND: case MILLISECOND: // These fields are handled simply, since they have fixed minima // and maxima. The field DAY_OF_MONTH is almost as simple. Other // fields are complicated, since the range within they must roll // varies depending on the date. break; case YEAR: /* if calendar set to 29th of February handle here the situation and return, else break */ (Incident Review ID: 186562) ======================================================================
|