aboutsummaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authorBryce McKinlay <bryce@waitaki.otago.ac.nz>2001-07-26 11:21:45 +0000
committerBryce McKinlay <bryce@gcc.gnu.org>2001-07-26 12:21:45 +0100
commitfa397ddafb335eb0a67b08e014605bf5f9ab7cc5 (patch)
treef1888f988daa008faa5d48c983f690f3067987c7 /libjava
parent2cf50fd3a47891bb7ae2a0ada9254ae7ef236a28 (diff)
downloadgcc-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/ChangeLog21
-rw-r--r--libjava/java/text/SimpleDateFormat.java143
-rw-r--r--libjava/java/util/Calendar.java5
-rw-r--r--libjava/java/util/GregorianCalendar.java14
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;