This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Calendar/Date fixes from Classpath


Hi guys,
I'd really like to see the following patch merged over from Classpath
and if possible into 4.0.0 ASAP. 
(the remaining differences are due to locale stuff, and since libgcj
isn't synced there, there's no point in that. that stuff is minor
anyway.)

As the code currently stands in libgcj CVS, timestamps are not going to
be parsed correctly. Most of them are going to be off by an hour.
This is due to two old bugs in Calendar and SimpleDateFormat which
cancel eachother out in a lot of cases. Calendar is expecting hours in
the wrong format, and SimpleDateFormat is parsing them in the wrong
format, and the whole thing is internally inconsistent with what Date
gives.

This patch *will* introduce several new mauve failures in the
java.util.Calendar.ampm testlet. (1,2,3,4,9,10,11,12) Sun fails on these
too, these tests are simply wrong, and I've explained why and sent a
patch for them to the Mavue-patches list about it. 
(Details:
http://sources.redhat.com/ml/mauve-patches/2005/msg00038.html )

The remaining Mauve failures in Calendar/GregorianCalendar should be
limited to:
test setting conflicting values of different fields (number 4) (bug)
test setting conflicting values of different fields (number 5) (nofix)

And the following: (all locale-related)
gnu.testlet.java.util.Calendar.set: setting only some fields (number 4)
gnu.testlet.java.util.Calendar.set: setting only some fields (number 5)
gnu.testlet.java.util.GregorianCalendar.getMinimalDaysInFirstWeek
(number 1)
gnu.testlet.java.util.GregorianCalendar.getMinimalDaysInFirstWeek
(number 2)

/Sven

2005-03-21  Sven de Marothy  <sven@physto.se>

	* java/util/Calendar.java
	(set): Use starting day of week when one is needed if none is given.
	* java/text/SimpleDateFormat.java
	(parse): Handle 1-12 and 1-24 timestamps correctly.
	* java/util/GregorianCalendar.java
	(computeTime, computeFields): HOUR should be in 0-11 format.
	(nonLeniencyCheck): Adjust leniency checking to that fact.
	(getLinearDay): Should be private.

Index: libjava/java/text/SimpleDateFormat.java
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/java/text/SimpleDateFormat.java,v
retrieving revision 1.32
diff -u -r1.32 SimpleDateFormat.java
--- libjava/java/text/SimpleDateFormat.java	23 Feb 2005 07:18:05 -0000	1.32
+++ libjava/java/text/SimpleDateFormat.java	20 Mar 2005 23:03:24 -0000
@@ -916,6 +916,8 @@
 	    boolean is_numeric = true;
 	    int offset = 0;
 	    boolean maybe2DigitYear = false;
+	    boolean oneBasedHour = false;
+	    boolean oneBasedHourOfDay = false;
 	    Integer simpleOffset;
 	    String[] set1 = null;
 	    String[] set2 = null;
@@ -964,12 +966,14 @@
 		break;
 	      case 'h':
 		calendar_field = Calendar.HOUR;
+		oneBasedHour = true;
 		break;
 	      case 'H':
 		calendar_field = Calendar.HOUR_OF_DAY;
 		break;
 	      case 'k':
 		calendar_field = Calendar.HOUR_OF_DAY;
+		oneBasedHourOfDay = true;
 		break;
 	      case 'm':
 		calendar_field = Calendar.MINUTE;
@@ -1108,6 +1112,14 @@
 		  }
 	      }
 	    
+	    // Calendar uses 0-based hours. 
+	    // I.e. 00:00 AM is midnight, not 12 AM or 24:00
+	    if (oneBasedHour && value == 12)
+	      value = 0;
+
+	    if (oneBasedHourOfDay && value == 24)
+	      value = 0;
+	    
 	    // Assign the value and move on.
 	    calendar.set(calendar_field, value);
 	  }
Index: libjava/java/util/Calendar.java
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/java/util/Calendar.java,v
retrieving revision 1.27
diff -u -r1.27 Calendar.java
--- libjava/java/util/Calendar.java	22 Feb 2005 13:02:10 -0000	1.27
+++ libjava/java/util/Calendar.java	20 Mar 2005 23:03:25 -0000
@@ -706,6 +706,8 @@
 	isSet[WEEK_OF_YEAR] = false;
 	break;
       case WEEK_OF_MONTH: // pattern 2
+	if (! isSet[DAY_OF_WEEK])
+	  fields[DAY_OF_WEEK] = getFirstDayOfWeek();
 	isSet[YEAR] = true;
 	isSet[MONTH] = true;
 	isSet[DAY_OF_WEEK] = true;
@@ -715,6 +717,8 @@
 	isSet[WEEK_OF_YEAR] = false;
 	break;
       case DAY_OF_WEEK_IN_MONTH: // pattern 3
+	if (! isSet[DAY_OF_WEEK])
+	  fields[DAY_OF_WEEK] = getFirstDayOfWeek();
 	isSet[YEAR] = true;
 	isSet[MONTH] = true;
 	isSet[DAY_OF_WEEK] = true;
@@ -733,6 +737,8 @@
 	isSet[DAY_OF_WEEK_IN_MONTH] = false;
 	break;
       case WEEK_OF_YEAR: // pattern 5
+	if (! isSet[DAY_OF_WEEK])
+	  fields[DAY_OF_WEEK] = getFirstDayOfWeek();
 	isSet[YEAR] = true;
 	isSet[DAY_OF_WEEK] = true;
 	isSet[MONTH] = false;
Index: libjava/java/util/GregorianCalendar.java
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/java/util/GregorianCalendar.java,v
retrieving revision 1.26
diff -u -r1.26 GregorianCalendar.java
--- libjava/java/util/GregorianCalendar.java	22 Feb 2005 00:58:36 -0000	1.26
+++ libjava/java/util/GregorianCalendar.java	20 Mar 2005 23:03:25 -0000
@@ -275,7 +275,6 @@
    * Constructs a new GregorianCalendar representing midnight on the
    * given date with the default time zone and locale.
    *
-   *
    * @param year corresponds to the YEAR time field.
    * @param month corresponds to the MONTH time field.
    * @param day corresponds to the DAY time field.
@@ -478,7 +477,7 @@
 
     if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM)
       throw new IllegalArgumentException("Illegal AM_PM.");
-    if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 12))
+    if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11))
       throw new IllegalArgumentException("Illegal HOUR.");
     if (isSet[HOUR_OF_DAY]
         && (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23))
@@ -564,10 +563,18 @@
 	    // 3: YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 	    if (isSet[DAY_OF_WEEK_IN_MONTH])
 	      {
+		if (fields[DAY_OF_WEEK_IN_MONTH] < 0)
+		  {
+		    month++;
+		    first = getFirstDayOfMonth(year, month);
+		    day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH]);
+		  }
+		else
+		  day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH] - 1);
+
 		int offs = fields[DAY_OF_WEEK] - first;
 		if (offs < 0)
 		  offs += 7;
-		day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH] - 1);
 		day += offs;
 	      }
 	    else
@@ -584,7 +591,7 @@
 
 		day = offs + 7 * (fields[WEEK_OF_MONTH] - 1);
 		offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek();
-		if (offs < 0)
+		if (offs <= 0)
 		  offs += 7;
 		day += offs;
 	      }
@@ -602,11 +609,7 @@
       {
 	hour = fields[HOUR];
 	if (fields[AM_PM] == PM)
-	  if (hour != 12) /* not Noon */
-	    hour += 12;
-	/* Fix the problem of the status of 12:00 AM (midnight). */
-	if (fields[AM_PM] == AM && hour == 12)
-	  hour = 0;
+	  hour += 12;
       }
     else
       hour = fields[HOUR_OF_DAY];
@@ -709,15 +712,15 @@
    * @param gregorian <code>true</code>, if we should use the Gregorian rules.
    * @return the days since the epoch, may be negative.
    */
-   public long getLinearDay(int year, int dayOfYear, boolean gregorian)
-    {
-     // The 13 is the number of days, that were omitted in the Gregorian
-     // Calender until the epoch.
-     // We shift right by 2 instead of dividing by 4, to get correct
-     // results for negative years (and this is even more efficient).
-     long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1)
-                      - EPOCH_DAYS; // gregorian days from 1 to epoch.
- 
+  private long getLinearDay(int year, int dayOfYear, boolean gregorian)
+  {
+    // The 13 is the number of days, that were omitted in the Gregorian
+    // Calender until the epoch.
+    // We shift right by 2 instead of dividing by 4, to get correct
+    // results for negative years (and this is even more efficient).
+    long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1)
+                     - EPOCH_DAYS; // gregorian days from 1 to epoch.
+
     if (gregorian)
       {
 	// subtract the days that are missing in gregorian calendar
@@ -858,7 +861,7 @@
     int hourOfDay = millisInDay / (60 * 60 * 1000);
     fields[AM_PM] = (hourOfDay < 12) ? AM : PM;
     int hour = hourOfDay % 12;
-    fields[HOUR] = (hour == 0) ? 12 : hour;
+    fields[HOUR] = hour;
     fields[HOUR_OF_DAY] = hourOfDay;
     millisInDay %= (60 * 60 * 1000);
     fields[MINUTE] = millisInDay / (60 * 1000);
@@ -925,9 +928,7 @@
 	  }
 	int maxDay = getActualMaximum(DAY_OF_MONTH);
 	if (fields[DAY_OF_MONTH] > maxDay)
-	  {
-	    fields[DAY_OF_MONTH] = maxDay;
-	  }
+	  fields[DAY_OF_MONTH] = maxDay;
 	set(YEAR, fields[YEAR]);
 	set(MONTH, fields[MONTH]);
 	break;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]