This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[patch] merge Calendar/Date fixes from classpath
- From: Andreas Tobler <toa at pop dot agri dot ch>
- To: Java Patches <java-patches at gcc dot gnu dot org>
- Date: Mon, 15 Nov 2004 22:53:39 +0100
- Subject: [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;