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]

[patch] merge Calendar/Date fixes from classpath


Hi all,

another one. Ok if no regressions from mauve?

Andreas

2004-11-15 Andreas Tobler <a.tobler@schweiz.ch>

Merge Calendar/Date fixes from Classpath:

2004-10-31 Noa Resare <noa@resare.com>

	* java/util/Calendar.java (explicitDSTOffset): New instance field.
	(set(int,int)): Set and use new field.
	(set(int,int,int)): Check new field.

2004-10-17 Jeroen Frijters <jeroen@frijters.net>

	* java/util/Calendar.java (setTimeInMillis): Added call to clear,
	removed computeFields call.
	* java/util/Date.java (Date(int,int,int,int,int,int)): Removed
	workaround for GregorianCalendar bug.
	* java/util/GregorianCalendar.java (GregorianCalendar): Chained all
	constructors to a (new) common constructor.
	(computeTime): Fixed support for lenient month treatment.
	(getLinearDay): Return long instead of int.
	(calculateDay): Added fields argument and changed day argument
	to long.

2004-10-12 Jeroen Frijters <jeroen@frijters.net>

	* java/util/Date.java (Date(int,int,int), Date(int,int,int,int,int)):
	Delegate to other constructor. (Date(int,int,int,int,int,int)): Fixed
	to handle out-of-range arguments.
	(getTimezoneOffset): Inverted sign.
Index: java/util/Calendar.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/util/Calendar.java,v
retrieving revision 1.25
diff -u -r1.25 Calendar.java
--- java/util/Calendar.java	22 Oct 2004 17:14:26 -0000	1.25
+++ java/util/Calendar.java	15 Nov 2004 21:47:01 -0000
@@ -347,6 +347,13 @@
   private int minimalDaysInFirstWeek;
 
   /**
+   * Is set to true if DST_OFFSET is explicitly set. In that case
+   * it's value overrides the value computed from the current
+   * time and the timezone. 
+   */
+  private boolean explicitDSTOffset = false;
+
+  /**
    * The version of the serialized data on the stream. 
    * <dl><dt>0 or not present</dt>
    * <dd> JDK 1.1.5 or later.</dd>
@@ -575,9 +582,9 @@
    */
   public void setTimeInMillis(long time)
   {
+    clear();
     this.time = time;
     isTimeSet = true;
-    computeFields();
   }
 
   /**
@@ -650,10 +657,12 @@
       case HOUR:
 	isSet[HOUR_OF_DAY] = false;
 	break;
+      case DST_OFFSET:
+        explicitDSTOffset = true;
       }
 
     // May have crossed over a DST boundary.
-    if (field != DST_OFFSET && field != ZONE_OFFSET)
+    if (!explicitDSTOffset && (field != DST_OFFSET && field != ZONE_OFFSET))
       isSet[DST_OFFSET] = false;
   }
 
@@ -676,7 +685,8 @@
     isSet[DAY_OF_WEEK] = false;
     isSet[DAY_OF_WEEK_IN_MONTH] = false;
 
-    isSet[DST_OFFSET] = false;  // May have crossed a DST boundary.
+    if (!explicitDSTOffset)
+      isSet[DST_OFFSET] = false;  // May have crossed a DST boundary.
   }
 
   /**
Index: java/util/Date.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/util/Date.java,v
retrieving revision 1.14
diff -u -r1.14 Date.java
--- java/util/Date.java	7 Nov 2004 11:17:46 -0000	1.14
+++ java/util/Date.java	15 Nov 2004 21:47:02 -0000
@@ -159,7 +159,7 @@
    */
   public Date(int year, int month, int day)
   {
-    time = new GregorianCalendar(year + 1900, month, day).getTimeInMillis();
+    this(year, month, day, 0, 0, 0);
   }
 
   /**
@@ -176,9 +176,7 @@
    */
   public Date(int year, int month, int day, int hour, int min)
   {
-    time =
-      new GregorianCalendar(year + 1900, month, day, hour,
-			    min).getTimeInMillis();
+    this(year, month, day, hour, min, 0);
   }
 
   /**
@@ -197,9 +195,9 @@
    */
   public Date(int year, int month, int day, int hour, int min, int sec)
   {
-    time =
-      new GregorianCalendar(year + 1900, month, day, hour, min,
-			    sec).getTimeInMillis();
+    GregorianCalendar cal =
+	new GregorianCalendar(year + 1900, month, day, hour, min, sec);
+    time = cal.getTimeInMillis();
   }
 
   /**
@@ -288,7 +286,7 @@
   {
     Calendar cal = Calendar.getInstance();
     cal.setTimeInMillis(time);
-    return (cal.get(Calendar.ZONE_OFFSET)
+    return - (cal.get(Calendar.ZONE_OFFSET)
 	    + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
   }
 
Index: java/util/GregorianCalendar.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/util/GregorianCalendar.java,v
retrieving revision 1.25
diff -u -r1.25 GregorianCalendar.java
--- java/util/GregorianCalendar.java	8 Nov 2004 23:04:34 -0000	1.25
+++ java/util/GregorianCalendar.java	15 Nov 2004 21:47:04 -0000
@@ -217,10 +217,22 @@
    */
   public GregorianCalendar(TimeZone zone, Locale locale)
   {
+    this(zone, locale, false);
+    setTimeInMillis(System.currentTimeMillis());
+  }
+
+  /**
+   * Common constructor that all constructors should call.
+   * @param zone a time zone.  
+   * @param locale a locale.  
+   * @param unused unused parameter to make the signature differ from
+   * the public constructor (TimeZone, Locale).
+   */
+  private GregorianCalendar(TimeZone zone, Locale locale, boolean unused)
+  {
     super(zone, locale);
     ResourceBundle rb = getBundle(locale);
     gregorianCutover = ((Date) rb.getObject("gregorianCutOver")).getTime();
-    setTimeInMillis(System.currentTimeMillis());
   }
 
   /**
@@ -232,7 +244,7 @@
    */
   public GregorianCalendar(int year, int month, int day)
   {
-    super();
+    this(TimeZone.getDefault(), Locale.getDefault(), false);
     set(year, month, day);
   }
 
@@ -248,7 +260,7 @@
    */
   public GregorianCalendar(int year, int month, int day, int hour, int minute)
   {
-    super();
+    this(TimeZone.getDefault(), Locale.getDefault(), false);
     set(year, month, day, hour, minute);
   }
 
@@ -267,7 +279,7 @@
   public GregorianCalendar(int year, int month, int day,
 			   int hour, int minute, int second)
   {
-    super();
+    this(TimeZone.getDefault(), Locale.getDefault(), false);
     set(year, month, day, hour, minute, second);
   }
 
@@ -503,6 +515,21 @@
   {
     int era = isSet[ERA] ? fields[ERA] : AD;
     int year = isSet[YEAR] ? fields[YEAR] : 1970;
+    if (isLenient() && isSet[MONTH])
+      {
+	int month = fields[MONTH];
+	year += month / 12;
+	month %= 12;
+	if (month < 0)
+	  {
+	    month += 12;
+	    year--;
+	  }
+	fields[MONTH] = month;
+	isSet[YEAR] = true;
+	fields[YEAR] = year;
+      }
+
     if (era == BC)
       year = 1 - year;
 
@@ -553,19 +580,20 @@
     int rawOffset = isSet[ZONE_OFFSET]
       ? fields[ZONE_OFFSET] : zone.getRawOffset();
 
-    int dayOfYear = daysOfYear[0] + daysOfYear[1];
-    // This formula isn't right, so check for month as a quick fix.
-    // It doesn't compensate for leap years and puts day 30 in month 1
-    // instead of month 0.
-    int month = isSet[MONTH]
-	? fields[MONTH] : (dayOfYear * 5 + 3) / (31 + 30 + 31 + 30 + 31);
-    // This formula isn't right, so check for day as a quick fix.  It
-    // doesn't compensate for leap years, either.
-    int day = isSet[DAY_OF_MONTH] ? fields[DAY_OF_MONTH]
-	: (6 + (dayOfYear * 5 + 3) % (31 + 30 + 31 + 30 + 31)) / 5;
-    int weekday = ((int) (time / (24 * 60 * 60 * 1000L)) + THURSDAY) % 7;
-    if (weekday <= 0)
-      weekday += 7;
+    int day = (int) (time / (24 * 60 * 60 * 1000L));
+    millisInDay = (int) (time % (24 * 60 * 60 * 1000L));
+    if (millisInDay < 0)
+      {
+	millisInDay += (24 * 60 * 60 * 1000);
+	day--;
+      }
+
+    int[] f = new int[FIELD_COUNT];
+    calculateDay(f, day, time - rawOffset >= gregorianCutover);
+    year = f[YEAR];
+    int month = f[MONTH];
+    day = f[DAY_OF_MONTH];
+    int weekday = f[DAY_OF_WEEK];
     int dstOffset = isSet[DST_OFFSET]
       ? fields[DST_OFFSET] : (zone.getOffset((year < 0) ? BC : AD,
 					     (year < 0) ? 1 - year : year,
@@ -613,13 +641,13 @@
    * @param gregorian <code>true</code>, if we should use the Gregorian rules.
    * @return the days since the epoch, may be negative.
    */
-  private int getLinearDay(int year, int dayOfYear, boolean gregorian)
+  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).
-    int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear -
+    long julianDay = ((year * (365L * 4 + 1)) >> 2) + dayOfYear -
       ((1970 * (365 * 4 + 1)) / 4 + 1 - 13);
 
     if (gregorian)
@@ -649,23 +677,23 @@
    * @param day the linear day.  
    * @param gregorian true, if we should use Gregorian rules.
    */
-  private void calculateDay(int day, boolean gregorian)
+  private void calculateDay(int[] fields, long day, boolean gregorian)
   {
     // the epoch is a Thursday.
-    int weekday = (day + THURSDAY) % 7;
+    int weekday = (int)(day + THURSDAY) % 7;
     if (weekday <= 0)
       weekday += 7;
     fields[DAY_OF_WEEK] = weekday;
 
     // get a first approximation of the year.  This may be one 
     // year too big.
-    int year = 1970 + (gregorian
+    int year = 1970 + (int)(gregorian
 		       ? ((day - 100) * 400) / (365 * 400 + 100 - 4 + 1)
 		       : ((day - 100) * 4) / (365 * 4 + 1));
     if (day >= 0)
       year++;
 
-    int firstDayOfYear = getLinearDay(year, 1, gregorian);
+    long firstDayOfYear = getLinearDay(year, 1, gregorian);
 
     // Now look in which year day really lies.
     if (day < firstDayOfYear)
@@ -676,7 +704,7 @@
 
     day -= firstDayOfYear - 1;	// day of year,  one based.
 
-    fields[DAY_OF_YEAR] = day;
+    fields[DAY_OF_YEAR] = (int)day;
     if (year <= 0)
       {
 	fields[ERA] = BC;
@@ -691,13 +719,13 @@
     int leapday = isLeapYear(year, gregorian) ? 1 : 0;
     if (day <= 31 + 28 + leapday)
       {
-	fields[MONTH] = day / 32;	// 31->JANUARY, 32->FEBRUARY
-	fields[DAY_OF_MONTH] = day - 31 * fields[MONTH];
+	fields[MONTH] = (int)day / 32; // 31->JANUARY, 32->FEBRUARY
+	fields[DAY_OF_MONTH] = (int)day - 31 * fields[MONTH];
       }
     else
       {
 	// A few more magic formulas
-	int scaledDay = (day - leapday) * 5 + 8;
+	int scaledDay = ((int)day - leapday) * 5 + 8;
 	fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31);
 	fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1;
       }
@@ -716,7 +744,7 @@
     fields[ZONE_OFFSET] = zone.getRawOffset();
     long localTime = time + fields[ZONE_OFFSET];
 
-    int day = (int) (localTime / (24 * 60 * 60 * 1000L));
+    long day = localTime / (24 * 60 * 60 * 1000L);
     int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));
     if (millisInDay < 0)
       {
@@ -724,7 +752,7 @@
 	day--;
       }
 
-    calculateDay(day, gregorian);
+    calculateDay(fields, day, gregorian);
     fields[DST_OFFSET] =
       zone.getOffset(fields[ERA], fields[YEAR], fields[MONTH],
 		     fields[DAY_OF_MONTH], fields[DAY_OF_WEEK],
@@ -734,7 +762,7 @@
     if (millisInDay >= 24 * 60 * 60 * 1000)
       {
 	millisInDay -= 24 * 60 * 60 * 1000;
-	calculateDay(++day, gregorian);
+	calculateDay(fields, ++day, gregorian);
       }
 
     fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7;

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