diff options
author | Bryce McKinlay <bryce@waitaki.otago.ac.nz> | 2001-07-26 11:21:45 +0000 |
---|---|---|
committer | Bryce McKinlay <bryce@gcc.gnu.org> | 2001-07-26 12:21:45 +0100 |
commit | fa397ddafb335eb0a67b08e014605bf5f9ab7cc5 (patch) | |
tree | f1888f988daa008faa5d48c983f690f3067987c7 /libjava | |
parent | 2cf50fd3a47891bb7ae2a0ada9254ae7ef236a28 (diff) | |
download | gcc-fa397ddafb335eb0a67b08e014605bf5f9ab7cc5.zip gcc-fa397ddafb335eb0a67b08e014605bf5f9ab7cc5.tar.gz gcc-fa397ddafb335eb0a67b08e014605bf5f9ab7cc5.tar.bz2 |
Calendar.java (set): Never recompute fields here.
* 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
Diffstat (limited to 'libjava')
-rw-r--r-- | libjava/ChangeLog | 21 | ||||
-rw-r--r-- | libjava/java/text/SimpleDateFormat.java | 143 | ||||
-rw-r--r-- | libjava/java/util/Calendar.java | 5 | ||||
-rw-r--r-- | libjava/java/util/GregorianCalendar.java | 14 |
4 files changed, 112 insertions, 71 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index bc5f522..15a2c56 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -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. diff --git a/libjava/java/text/SimpleDateFormat.java b/libjava/java/text/SimpleDateFormat.java index 80ab6ea..8d914fb 100644 --- a/libjava/java/text/SimpleDateFormat.java +++ b/libjava/java/text/SimpleDateFormat.java @@ -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()); } } diff --git a/libjava/java/util/Calendar.java b/libjava/java/util/Calendar.java index 17f4c77..8149411 100644 --- a/libjava/java/util/Calendar.java +++ b/libjava/java/util/Calendar.java @@ -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; diff --git a/libjava/java/util/GregorianCalendar.java b/libjava/java/util/GregorianCalendar.java index 1a8d073..2c68907 100644 --- a/libjava/java/util/GregorianCalendar.java +++ b/libjava/java/util/GregorianCalendar.java @@ -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; |