]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Calendar.java (set): Never recompute fields here.
authorBryce McKinlay <bryce@waitaki.otago.ac.nz>
Thu, 26 Jul 2001 11:21:45 +0000 (11:21 +0000)
committerBryce McKinlay <bryce@gcc.gnu.org>
Thu, 26 Jul 2001 11:21:45 +0000 (12:21 +0100)
* java/util/Calendar.java (set): Never recompute fields here. They
will already be set if someone set time explicitly, and it can cause
problems to do so. Don't invalidate AM_PM setting if HOUR is set.
* java/util/GregorianCalendar.java (computeTime): Don't ignore an
HOUR setting if AM_PM is set. Don't try to ensure the HOUR value is
sane.
* java/text/SimpleDateFormat.java (defaultCentury): New field.
(readObject): Call set2DigitYearStart if appropriate so that
defaultCentury is calculated.
(SimpleDateFormat): Don't bother clearing calendar here. Call
computeCenturyStart().
(set2DigitYearStart): Calculate and set defaultCentury.
(format): Don't clone the calendar. Use "calendar" not "theCalendar"
everywhere.
(parse): Likewise. If the pattern is "y" or "yy" and it found exactly
2 numeric digits, use the 80-20 heuristic to parse the value into a
default century based on defaultCenturyStart.
(computeCenturyStart): Rewritten. Call set2DigitYearStart().

From-SVN: r44395

libjava/ChangeLog
libjava/java/text/SimpleDateFormat.java
libjava/java/util/Calendar.java
libjava/java/util/GregorianCalendar.java

index bc5f52207e74ef99c037e162f182b50f2cd8f759..15a2c566acb0b1d649a7cd2d1be0699f3fce6b6e 100644 (file)
@@ -1,3 +1,24 @@
+2001-07-26  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>
+
+       * java/util/Calendar.java (set): Never recompute fields here. They 
+       will already be set if someone set time explicitly, and it can cause
+       problems to do so. Don't invalidate AM_PM setting if HOUR is set.
+       * java/util/GregorianCalendar.java (computeTime): Don't ignore an
+       HOUR setting if AM_PM is set. Don't try to ensure the HOUR value is 
+       sane.
+       * java/text/SimpleDateFormat.java (defaultCentury): New field.
+       (readObject): Call set2DigitYearStart if appropriate so that 
+       defaultCentury is calculated.
+       (SimpleDateFormat): Don't bother clearing calendar here. Call
+       computeCenturyStart().
+       (set2DigitYearStart): Calculate and set defaultCentury.
+       (format): Don't clone the calendar. Use "calendar" not "theCalendar"
+       everywhere.
+       (parse): Likewise. If the pattern is "y" or "yy" and it found exactly
+       2 numeric digits, use the 80-20 heuristic to parse the value into a
+       default century based on defaultCenturyStart.
+       (computeCenturyStart): Rewritten. Call set2DigitYearStart().
+
 2001-07-25  Tom Tromey  <tromey@redhat.com>
 
        * Makefile.in: Rebuilt.
index 80ab6ea73095de1529eaae75e3c338fbb0950a90..8d914fb3ebfea986a81f2001c741763da4991a97 100644 (file)
@@ -62,7 +62,8 @@ public class SimpleDateFormat extends DateFormat
 
   private transient Vector tokens;
   private DateFormatSymbols formatData;  // formatData
-  private Date defaultCenturyStart = computeCenturyStart ();
+  private Date defaultCenturyStart;
+  private transient int defaultCentury;
   private String pattern;
   private int serialVersionOnStream = 1; // 0 indicates JDK1.1.3 or earlier
   private static final long serialVersionUID = 4774881970558875024L;
@@ -78,9 +79,12 @@ public class SimpleDateFormat extends DateFormat
     stream.defaultReadObject();
     if (serialVersionOnStream < 1)
       {
-        defaultCenturyStart = computeCenturyStart ();
+        computeCenturyStart ();
        serialVersionOnStream = 1;
       }
+    else
+      // Ensure that defaultCentury gets set.
+      set2DigitYearStart(defaultCenturyStart);
 
     // Set up items normally taken care of by the constructor.
     tokens = new Vector();
@@ -159,7 +163,7 @@ public class SimpleDateFormat extends DateFormat
     super();
     Locale locale = Locale.getDefault();
     calendar = new GregorianCalendar(locale);
-    calendar.clear ();
+    computeCenturyStart();
     tokens = new Vector();
     formatData = new DateFormatSymbols(locale);
     pattern = (formatData.dateFormats[DEFAULT] + ' '
@@ -186,7 +190,7 @@ public class SimpleDateFormat extends DateFormat
   {
     super();
     calendar = new GregorianCalendar(locale);
-    calendar.clear ();
+    computeCenturyStart();
     tokens = new Vector();
     formatData = new DateFormatSymbols(locale);
     compileFormat(pattern);
@@ -203,10 +207,6 @@ public class SimpleDateFormat extends DateFormat
   {
     super();
     calendar = new GregorianCalendar();
-    calendar.clear ();
-    // FIXME: XXX: Is it really necessary to set the timezone?
-    // The Calendar constructor is supposed to take care of this.
-    calendar.setTimeZone(TimeZone.getDefault());
     tokens = new Vector();
     this.formatData = formatData;
     compileFormat(pattern);
@@ -309,6 +309,10 @@ public class SimpleDateFormat extends DateFormat
   public void set2DigitYearStart(Date date)
   {
     defaultCenturyStart = date;
+    calendar.clear();
+    calendar.setTime(date);
+    int year = calendar.get(Calendar.YEAR);
+    defaultCentury = year - (year % 100);
   }
 
   /**
@@ -386,8 +390,7 @@ public class SimpleDateFormat extends DateFormat
   public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos)
   {
     String temp;
-    Calendar theCalendar = (Calendar) calendar.clone();
-    theCalendar.setTime(date);
+    calendar.setTime(date);
     
     // go through vector, filling in fields where applicable, else toString
     Enumeration e = tokens.elements();
@@ -398,10 +401,10 @@ public class SimpleDateFormat extends DateFormat
        int beginIndex = buffer.length();
        switch (p.field) {
        case ERA_FIELD:
-         buffer.append(formatData.eras[theCalendar.get(Calendar.ERA)]);
+         buffer.append(formatData.eras[calendar.get(Calendar.ERA)]);
          break;
        case YEAR_FIELD:
-         temp = String.valueOf(theCalendar.get(Calendar.YEAR));
+         temp = String.valueOf(calendar.get(Calendar.YEAR));
          if (p.size < 4)
            buffer.append(temp.substring(temp.length()-2));
          else
@@ -409,60 +412,60 @@ public class SimpleDateFormat extends DateFormat
          break;
        case MONTH_FIELD:
          if (p.size < 3)
-           withLeadingZeros(theCalendar.get(Calendar.MONTH)+1,p.size,buffer);
+           withLeadingZeros(calendar.get(Calendar.MONTH)+1,p.size,buffer);
          else if (p.size < 4)
-           buffer.append(formatData.shortMonths[theCalendar.get(Calendar.MONTH)]);
+           buffer.append(formatData.shortMonths[calendar.get(Calendar.MONTH)]);
          else
-           buffer.append(formatData.months[theCalendar.get(Calendar.MONTH)]);
+           buffer.append(formatData.months[calendar.get(Calendar.MONTH)]);
          break;
        case DATE_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.DATE),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.DATE),p.size,buffer);
          break;
        case HOUR_OF_DAY1_FIELD: // 1-24
-         withLeadingZeros(((theCalendar.get(Calendar.HOUR_OF_DAY)+23)%24)+1,p.size,buffer);
+         withLeadingZeros(((calendar.get(Calendar.HOUR_OF_DAY)+23)%24)+1,p.size,buffer);
          break;
        case HOUR_OF_DAY0_FIELD: // 0-23
-         withLeadingZeros(theCalendar.get(Calendar.HOUR_OF_DAY),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.HOUR_OF_DAY),p.size,buffer);
          break;
        case MINUTE_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.MINUTE),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.MINUTE),p.size,buffer);
          break;
        case SECOND_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.SECOND),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.SECOND),p.size,buffer);
          break;
        case MILLISECOND_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.MILLISECOND),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.MILLISECOND),p.size,buffer);
          break;
        case DAY_OF_WEEK_FIELD:
          if (p.size < 4)
-           buffer.append(formatData.shortWeekdays[theCalendar.get(Calendar.DAY_OF_WEEK)]);
+           buffer.append(formatData.shortWeekdays[calendar.get(Calendar.DAY_OF_WEEK)]);
          else
-           buffer.append(formatData.weekdays[theCalendar.get(Calendar.DAY_OF_WEEK)]);
+           buffer.append(formatData.weekdays[calendar.get(Calendar.DAY_OF_WEEK)]);
          break;
        case DAY_OF_YEAR_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.DAY_OF_YEAR),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.DAY_OF_YEAR),p.size,buffer);
          break;
        case DAY_OF_WEEK_IN_MONTH_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.DAY_OF_WEEK_IN_MONTH),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH),p.size,buffer);
          break;
        case WEEK_OF_YEAR_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.WEEK_OF_YEAR),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.WEEK_OF_YEAR),p.size,buffer);
          break;
        case WEEK_OF_MONTH_FIELD:
-         withLeadingZeros(theCalendar.get(Calendar.WEEK_OF_MONTH),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.WEEK_OF_MONTH),p.size,buffer);
          break;
        case AM_PM_FIELD:
-         buffer.append(formatData.ampms[theCalendar.get(Calendar.AM_PM)]);
+         buffer.append(formatData.ampms[calendar.get(Calendar.AM_PM)]);
          break;
        case HOUR1_FIELD: // 1-12
-         withLeadingZeros(((theCalendar.get(Calendar.HOUR)+11)%12)+1,p.size,buffer);
+         withLeadingZeros(((calendar.get(Calendar.HOUR)+11)%12)+1,p.size,buffer);
          break;
        case HOUR0_FIELD: // 0-11
-         withLeadingZeros(theCalendar.get(Calendar.HOUR),p.size,buffer);
+         withLeadingZeros(calendar.get(Calendar.HOUR),p.size,buffer);
          break;
        case TIMEZONE_FIELD:
-         TimeZone zone = theCalendar.getTimeZone();
-         boolean isDST = theCalendar.get(Calendar.DST_OFFSET) != 0;
+         TimeZone zone = calendar.getTimeZone();
+         boolean isDST = calendar.get(Calendar.DST_OFFSET) != 0;
          // FIXME: XXX: This should be a localized time zone.
          String zoneID = zone.getDisplayName(isDST, p.size > 3 ? TimeZone.LONG : TimeZone.SHORT);
          buffer.append(zoneID);
@@ -482,7 +485,8 @@ public class SimpleDateFormat extends DateFormat
     return buffer;
   }
 
-  private void withLeadingZeros(int value, int length, StringBuffer buffer) {
+  private void withLeadingZeros(int value, int length, StringBuffer buffer) 
+  {
     String valStr = String.valueOf(value);
     for (length -= valStr.length(); length > 0; length--)
       buffer.append('0');
@@ -514,12 +518,10 @@ public class SimpleDateFormat extends DateFormat
     int fmt_index = 0;
     int fmt_max = pattern.length();
 
-    // We copy the Calendar because if we don't we will modify it and
-    // then this.equals() will no longer have the desired result.
-    Calendar theCalendar = (Calendar) calendar.clone ();
-    theCalendar.clear();
+    calendar.clear();
     boolean saw_timezone = false;
     int quote_start = -1;
+    boolean is2DigitYear = false;
     for (; fmt_index < fmt_max; ++fmt_index)
       {
        char ch = pattern.charAt(fmt_index);
@@ -552,7 +554,7 @@ public class SimpleDateFormat extends DateFormat
        int first = fmt_index;
        while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
          ;
-       int count = fmt_index - first;
+       int fmt_count = fmt_index - first;
        --fmt_index;
 
        // We can handle most fields automatically: most either are
@@ -564,6 +566,7 @@ public class SimpleDateFormat extends DateFormat
        boolean is_numeric = true;
        String[] match = null;
        int offset = 0;
+       boolean maybe2DigitYear = false;
        switch (ch)
          {
          case 'd':
@@ -579,7 +582,7 @@ public class SimpleDateFormat extends DateFormat
            is_numeric = false;
            offset = 1;
            calendar_field = Calendar.DAY_OF_WEEK;
-           match = (count <= 3
+           match = (fmt_count <= 3
                     ? formatData.getShortWeekdays()
                     : formatData.getWeekdays());
            break;
@@ -591,20 +594,20 @@ public class SimpleDateFormat extends DateFormat
            break;
          case 'M':
            calendar_field = Calendar.MONTH;
-           if (count <= 2)
+           if (fmt_count <= 2)
              offset = -1;
            else
              {
                is_numeric = false;
-               match = (count <= 3
+               match = (fmt_count <= 3
                         ? formatData.getShortMonths()
                         : formatData.getMonths());
              }
            break;
          case 'y':
            calendar_field = Calendar.YEAR;
-           if (count <= 2)
-             offset = 1900;
+           if (fmt_count <= 2)
+             maybe2DigitYear = true;
            break;
          case 'K':
            calendar_field = Calendar.HOUR;
@@ -655,8 +658,8 @@ public class SimpleDateFormat extends DateFormat
                    found_zone = true;
                    saw_timezone = true;
                    TimeZone tz = TimeZone.getTimeZone (strings[0]);
-                   theCalendar.setTimeZone (tz);
-                   theCalendar.set (Calendar.ZONE_OFFSET, tz.getRawOffset ());
+                   calendar.setTimeZone (tz);
+                   calendar.set (Calendar.ZONE_OFFSET, tz.getRawOffset ());
                    offset = 0;
                    if (k > 2 && tz instanceof SimpleTimeZone)
                      {
@@ -680,9 +683,12 @@ public class SimpleDateFormat extends DateFormat
 
        // Compute the value we should assign to the field.
        int value;
+       int index = -1;
        if (is_numeric)
          {
-           numberFormat.setMinimumIntegerDigits(count);
+           numberFormat.setMinimumIntegerDigits(fmt_count);
+           if (maybe2DigitYear)
+             index = pos.getIndex();
            Number n = numberFormat.parse(dateStr, pos);
            if (pos == null || ! (n instanceof Long))
              return null;
@@ -690,7 +696,7 @@ public class SimpleDateFormat extends DateFormat
          }
        else if (match != null)
          {
-           int index = pos.getIndex();
+           index = pos.getIndex();
            int i;
            for (i = offset; i < match.length; ++i)
              {
@@ -707,9 +713,28 @@ public class SimpleDateFormat extends DateFormat
          }
        else
          value = offset;
+         
+       if (maybe2DigitYear)
+         {
+           // Parse into default century if the numeric year string has 
+           // exactly 2 digits.
+           int digit_count = pos.getIndex() - index;
+           if (digit_count == 2)
+             is2DigitYear = true;
+         }
 
        // Assign the value and move on.
-       theCalendar.set(calendar_field, value);
+       calendar.set(calendar_field, value);
+      }
+    
+    if (is2DigitYear)
+      {
+       // Apply the 80-20 heuristic to dermine the full year based on 
+       // defaultCenturyStart. 
+       int year = defaultCentury + calendar.get(Calendar.YEAR);
+       calendar.set(Calendar.YEAR, year);
+       if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
+         calendar.set(Calendar.YEAR, year + 100);      
       }
 
     try
@@ -718,10 +743,10 @@ public class SimpleDateFormat extends DateFormat
          {
            // Use the real rules to determine whether or not this
            // particular time is in daylight savings.
-           theCalendar.clear (Calendar.DST_OFFSET);
-           theCalendar.clear (Calendar.ZONE_OFFSET);
+           calendar.clear (Calendar.DST_OFFSET);
+           calendar.clear (Calendar.ZONE_OFFSET);
          }
-        return theCalendar.getTime();
+        return calendar.getTime();
       }
     catch (IllegalArgumentException x)
       {
@@ -732,18 +757,10 @@ public class SimpleDateFormat extends DateFormat
 
   // Compute the start of the current century as defined by
   // get2DigitYearStart.
-  private Date computeCenturyStart ()
+  private void computeCenturyStart()
   {
-    // Compute the current year.  We assume a year has 365 days.  Then
-    // compute 80 years ago, and finally reconstruct the number of
-    // milliseconds.  We do this computation in this strange way
-    // because it lets us easily truncate the milliseconds, seconds,
-    // etc, which don't matter and which confuse
-    // SimpleDateFormat.equals().
-    long now = System.currentTimeMillis ();
-    now /= 365L * 24L * 60L * 60L * 1000L;
-    now -= 80;
-    now *= 365L * 24L * 60L * 60L * 1000L;
-    return new Date (now);
+    int year = calendar.get(Calendar.YEAR);
+    calendar.set(Calendar.YEAR, year - 80);
+    set2DigitYearStart(calendar.getTime());
   }
 }
index 17f4c7756e597a1119e8278d3f9b7912be2ed3ba..81494112533038d95ea1fcc77fcb7b0d4a1605e9 100644 (file)
@@ -549,8 +549,6 @@ public abstract class Calendar implements Serializable, Cloneable
    */
   public final void set(int field, int value)
   {
-    if (!areFieldsSet)
-      computeFields();
     isTimeSet = false;
     fields[field] = value;
     isSet[field] = true;
@@ -573,7 +571,6 @@ public abstract class Calendar implements Serializable, Cloneable
        isSet[HOUR] = false;
        break;
       case HOUR:
-       isSet[AM_PM] = false;
        isSet[HOUR_OF_DAY] = false;
        break;
       }
@@ -587,8 +584,6 @@ public abstract class Calendar implements Serializable, Cloneable
    */
   public final void set(int year, int month, int date)
   {
-    if (!areFieldsSet)
-      computeFields();
     isTimeSet = false;
     fields[YEAR] = year;
     fields[MONTH] = month;
index 1a8d073da2f94672a5fc45aadb71acdf1d44a8dc..2c68907bac4a82f03d2218d19e8035aa6f27e25e 100644 (file)
@@ -373,9 +373,17 @@ public class GregorianCalendar extends Calendar
       year = 1 - year;
 
     int[] daysOfYear = getDayOfYear(year);
-    int hour = isSet[HOUR_OF_DAY] ? fields[HOUR_OF_DAY]
-      : (isSet[HOUR] && isSet[AM_PM]
-        ? fields[AM_PM] * 12 + (fields[HOUR] % 12) : 0);
+
+    int hour = 0;
+    if (isSet[HOUR_OF_DAY])
+      hour = fields[HOUR_OF_DAY];
+    else if (isSet[HOUR])
+      {
+       hour = fields[HOUR];
+        if (isSet[AM_PM] && fields[AM_PM] == PM)
+         hour += 12;
+      }
+
     int minute = isSet[MINUTE] ? fields[MINUTE] : 0;
     int second = isSet[SECOND] ? fields[SECOND] : 0;
     int millis = isSet[MILLISECOND] ? fields[MILLISECOND] : 0;