Commit a6f5b6f9 by Warren Levy Committed by Warren Levy

natSystem.cc (getSystemTimeZone): Adjust for DST.

	* java/lang/natSystem.cc (getSystemTimeZone): Adjust for DST.
	* java/text/SimpleDateFormat.java
	(indexInArray): Removed private method.
	(processYear): Removed private method.
	(parseLenient): Removed private method.
	(parseLeadingZeros): Removed private method.
	(parseStrict): Removed private method.
	(expect): Added new private method.
	(parse): Reverted to pre-Classpath merge version with minor fixes.
	* java/util/natGregorianCalendar.cc (computeTime): Handle strict
	calendars.

From-SVN: r41456
parent 7471a1f0
2001-04-20 Warren Levy <warrenl@redhat.com>
* java/lang/natSystem.cc (getSystemTimeZone): Adjust for DST.
* java/text/SimpleDateFormat.java
(indexInArray): Removed private method.
(processYear): Removed private method.
(parseLenient): Removed private method.
(parseLeadingZeros): Removed private method.
(parseStrict): Removed private method.
(expect): Added new private method.
(parse): Reverted to pre-Classpath merge version with minor fixes.
* java/util/natGregorianCalendar.cc (computeTime): Handle strict
calendars.
2001-04-12 Bryce McKinlay <bryce@albatross.co.nz> 2001-04-12 Bryce McKinlay <bryce@albatross.co.nz>
* java/io/File.java (normalizePath): New private method. * java/io/File.java (normalizePath): New private method.
......
...@@ -249,9 +249,11 @@ java::lang::System::getSystemTimeZone (void) ...@@ -249,9 +249,11 @@ java::lang::System::getSystemTimeZone (void)
mktime(tim = localtime(&current_time)); mktime(tim = localtime(&current_time));
#ifdef STRUCT_TM_HAS_GMTOFF #ifdef STRUCT_TM_HAS_GMTOFF
tzoffset = -(tim->tm_gmtoff); // tm_gmtoff is secs EAST of UTC. // tm_gmtoff is secs EAST of UTC.
tzoffset = -(tim->tm_gmtoff) + tim->tm_isdst * 3600L;
#elif HAVE_TIMEZONE #elif HAVE_TIMEZONE
tzoffset = timezone; // timezone is secs WEST of UTC. // timezone is secs WEST of UTC.
tzoffset = timezone;
#else #else
// FIXME: there must be another global if neither tm_gmtoff nor timezone // FIXME: there must be another global if neither tm_gmtoff nor timezone
// is available, esp. if tzname is valid. // is available, esp. if tzname is valid.
......
...@@ -482,679 +482,228 @@ public class SimpleDateFormat extends DateFormat ...@@ -482,679 +482,228 @@ public class SimpleDateFormat extends DateFormat
buffer.append(valStr); buffer.append(valStr);
} }
private int indexInArray(String dateStr, int index, String[] values) { private final boolean expect (String source, ParsePosition pos, char ch)
int l1 = dateStr.length()-index;
int l2;
for (int i=0; i < values.length; i++) {
if (values[i] == null)
continue;
l2 = values[i].length();
//System.err.println(values[i] + " " + dateStr.substring(index,index+l2));
if ((l1 >= l2) && (dateStr.substring(index,index+l2).equals(values[i])))
return i;
}
return -1;
}
/*
* Get the actual year value, converting two digit years if necessary.
*/
private int processYear(int val)
{ {
if (val > 100) int x = pos.getIndex();
return val; boolean r = x < source.length() && source.charAt(x) == ch;
if (r)
Date d = get2DigitYearStart(); pos.setIndex(x + 1);
Calendar c = Calendar.getInstance(); else
c.setTime(d); pos.setErrorIndex(x);
int y = c.get(YEAR_FIELD); return r;
return ((y / 100) * 100) + val;
} }
/* /**
* Ok, we ignore the format string and just try to parse what we can * This method parses the specified string into a date.
* out of the string. We need, month, day, year at a minimum. The real *
* killer is stuff like XX/XX/XX. How do we interpret that? Is is the * @param dateStr The date string to parse.
* US style MM/DD/YY or the European style DD/MM/YY. Or is it YYYY/MM/DD? * @param pos The input and output parse position
* I'm an American, so I guess you know which one I'm choosing.... *
* @return The parsed date, or <code>null</code> if the string cannot be
* parsed.
*/ */
private Date parseLenient(String dateStr, ParsePosition pos) public Date parse (String dateStr, ParsePosition pos)
{ {
int month = -1; int fmt_index = 0;
int day = -1; int fmt_max = pattern.length();
int year = -1;
int era = -1;
int hour = -1;
int hour24 = -1;
int minute = -1;
int second = -1;
int millis = -1;
int ampm = -1;
int last = -1;
TimeZone tz = null;
char lastsep = ' ';
char nextchar = ' ';
Calendar cal = (Calendar)calendar.clone();
cal.clear();
cal.setTime(new Date(0));
int index = pos.getIndex();
String buf = dateStr.substring(index, dateStr.length());
top: calendar.clear();
for(;;) int quote_start = -1;
for (; fmt_index < fmt_max; ++fmt_index)
{ {
char ch = pattern.charAt(fmt_index);
// Are we at the end of the string? If so, make sure we have if (ch == '\'')
// enough data and return. // FIXME: Also detect sufficient data
// and return by setting buf to "" on an unparsible string.
if (buf.equals(""))
{ {
pos.setIndex(index); int index = pos.getIndex();
if (fmt_index < fmt_max - 1
// This is the minimum we need && pattern.charAt(fmt_index + 1) == '\'')
if ((month == -1) || (day == -1) || (year == -1))
{ {
pos.setErrorIndex(index); if (! expect (dateStr, pos, ch))
return null; return null;
} ++fmt_index;
if (tz != null)
cal.setTimeZone(tz);
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1);
cal.set(Calendar.DATE, day);
if (ampm == 0)
cal.set(Calendar.AM_PM, Calendar.AM);
else if (ampm == 1)
cal.set(Calendar.AM_PM, Calendar.PM);
// If am/pm not set, we assume 24 hour day
if (hour != -1)
{
if (ampm == -1)
cal.set(Calendar.HOUR_OF_DAY, hour);
else
{
if (ampm == 0)
{
if (hour == 12)
hour = 0;
} }
else else
{ quote_start = quote_start < 0 ? fmt_index : -1;
if (hour != 12)
hour += 12;
}
cal.set(Calendar.HOUR_OF_DAY, hour);
}
}
if (minute != -1)
cal.set(Calendar.MINUTE, minute);
if (second != -1)
cal.set(Calendar.SECOND, second);
if (millis != -1)
cal.set(Calendar.MILLISECOND, millis);
if (era == 0)
cal.set(Calendar.ERA, GregorianCalendar.BC);
else if (era == 1)
cal.set(Calendar.ERA, GregorianCalendar.AD);
return cal.getTime();
}
// Skip over whitespace and expected punctuation
char c = buf.charAt(0);
boolean comma_found = false;
while(Character.isWhitespace(c) || (c == ':') ||
(c == ',') || (c == '.') || (c == '/'))
{
lastsep = c;
if (c == ',') // This is a total and utter crock
comma_found = true;
buf = buf.substring(1);
if (buf.equals(""))
continue; continue;
c = buf.charAt(0);
}
if (comma_found == true)
lastsep = ',';
// Is it a month name?
for (int i = 0; i < formatData.months.length; i++)
if ((formatData.months[i] != null)
&& buf.startsWith(formatData.months[i]))
{
month = i + 1;
buf = buf.substring(formatData.months[i].length());
index += formatData.months[i].length();
last = MONTH_FIELD;
continue top;
} }
// Is it a short month name? if (quote_start != -1
for (int i = 0; i < formatData.shortMonths.length; i++) || ((ch < 'a' || ch > 'z')
if ((formatData.shortMonths[i] != null) && (ch < 'A' || ch > 'Z')))
&& buf.startsWith(formatData.shortMonths[i]))
{ {
month = i + 1; if (! expect (dateStr, pos, ch))
buf = buf.substring(formatData.shortMonths[i].length()); return null;
index += formatData.shortMonths[i].length(); continue;
last = MONTH_FIELD;
continue top;
}
// Is it a weekday name?
for (int i = 0; i < formatData.weekdays.length; i++)
if ((formatData.weekdays[i] != null)
&& buf.startsWith(formatData.weekdays[i]))
{
buf = buf.substring(formatData.weekdays[i].length());
index += formatData.weekdays[i].length();
last = DAY_OF_WEEK_FIELD;
continue top;
}
// Is it a short weekday name?
for (int i = 0; i < formatData.shortWeekdays.length; i++)
if ((formatData.shortWeekdays[i] != null)
&& buf.startsWith(formatData.shortWeekdays[i]))
{
buf = buf.substring(formatData.shortWeekdays[i].length());
index += formatData.shortWeekdays[i].length();
last = DAY_OF_WEEK_FIELD;
continue top;
} }
// Is this an am/pm string? // We've arrived at a potential pattern character in the
for (int i = 0; i < formatData.ampms.length; i++) { // pattern.
if ((formatData.ampms[i] != null) int first = fmt_index;
&& buf.toLowerCase().startsWith(formatData.ampms[i].toLowerCase())) while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
;
int count = fmt_index - first;
--fmt_index;
// We can handle most fields automatically: most either are
// numeric or are looked up in a string vector. In some cases
// we need an offset. When numeric, `offset' is added to the
// resulting value. When doing a string lookup, offset is the
// initial index into the string array.
int calendar_field;
boolean is_numeric = true;
String[] match = null;
int offset = 0;
int zone_number = 0;
switch (ch)
{
case 'd':
calendar_field = Calendar.DATE;
break;
case 'D':
calendar_field = Calendar.DAY_OF_YEAR;
break;
case 'F':
calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
break;
case 'E':
is_numeric = false;
offset = 1;
calendar_field = Calendar.DAY_OF_WEEK;
match = (count <= 3
? formatData.getShortWeekdays()
: formatData.getWeekdays());
break;
case 'w':
calendar_field = Calendar.WEEK_OF_YEAR;
break;
case 'W':
calendar_field = Calendar.WEEK_OF_MONTH;
break;
case 'M':
calendar_field = Calendar.MONTH;
if (count <= 2)
offset = -1;
else
{ {
ampm = i; is_numeric = false;
buf = buf.substring(formatData.ampms[i].length()); match = (count <= 3
index += formatData.ampms[i].length(); ? formatData.getShortMonths()
last = AM_PM_FIELD; : formatData.getMonths());
continue top;
} }
}
// See if we have a number
c = buf.charAt(0);
String nbrstr = "";
while (Character.isDigit(c))
{
nbrstr = nbrstr + c;
buf = buf.substring(1);
if (buf.equals(""))
break; break;
c = buf.charAt(0); case 'y':
} calendar_field = Calendar.YEAR;
if (count <= 2)
// If we didn't get a number, try for a timezone, otherwise set buf offset = 1900;
// to "" and loop to see if we are done.
if (nbrstr.equals(""))
{
// Ok, try for a timezone name
while(!Character.isWhitespace(c) && (c != ',') && (c != '.') &&
(c != ':') && (c != '/'))
{
nbrstr = nbrstr + c;
buf = buf.substring(1);
if (buf.equals(""))
break; break;
c = buf.charAt(0); case 'K':
} calendar_field = Calendar.HOUR;
TimeZone tmptz = TimeZone.getTimeZone(nbrstr); break;
case 'h':
// We get GMT on failure, so be sure we asked for it. calendar_field = Calendar.HOUR;
if (tmptz.getID().equals("GMT")) break;
{ case 'H':
if (!nbrstr.equals("GMT")) calendar_field = Calendar.HOUR_OF_DAY;
{ break;
buf = ""; case 'k':
continue top; calendar_field = Calendar.HOUR_OF_DAY;
} break;
} case 'm':
calendar_field = Calendar.MINUTE;
tz = tmptz; break;
last = TIMEZONE_FIELD; case 's':
index += nbrstr.length(); calendar_field = Calendar.SECOND;
continue top; break;
} case 'S':
calendar_field = Calendar.MILLISECOND;
// Convert to integer break;
int val = 0; case 'a':
try is_numeric = false;
{ calendar_field = Calendar.AM_PM;
val = Integer.parseInt(nbrstr); match = formatData.getAmPmStrings();
} break;
catch(Exception e) case 'z':
{ // We need a special case for the timezone, because it
return null; // Shouldn't happen // uses a different data structure than the other cases.
} is_numeric = false;
calendar_field = Calendar.DST_OFFSET;
if (!buf.equals("")) String[][] zoneStrings = formatData.getZoneStrings();
nextchar = buf.charAt(0); int zoneCount = zoneStrings.length;
else
nextchar = ' ';
// Figure out which value to assign to
// I make bad US assumptions about MM/DD/YYYY
if (last == DAY_OF_WEEK_FIELD)
{
day = val;
last = DATE_FIELD;
}
else if ((last == MONTH_FIELD) && (day != -1))
{
year = processYear(val);
last = YEAR_FIELD;
}
else if (last == MONTH_FIELD)
{
day = val;
last = DATE_FIELD;
}
else if (last == -1)
{
// Assume month
if ((val < 13) && (val > 0))
{
month = val;
last = MONTH_FIELD;
}
// Assume year. This only works for two digit years that aren't
// between 01 and 12
else
{
year = processYear(val);
last = YEAR_FIELD;
}
}
else if ((last == YEAR_FIELD) && ((nextchar == '/') ||
(nextchar == '.')))
{
month = val;
last = MONTH_FIELD;
}
else if (last == YEAR_FIELD)
{
hour = val;
last = HOUR0_FIELD;
}
else if ((last == DATE_FIELD) && ((nextchar == '/') ||
(nextchar == '.') || buf.equals("")))
{
year = processYear(val);
last = YEAR_FIELD;
}
else if ((last == DATE_FIELD) && ((lastsep == '/') ||
(lastsep == '.') || (lastsep == ',')))
{
year = processYear(val);
last = YEAR_FIELD;
}
else if (last == DATE_FIELD)
{
hour = val;
last = HOUR0_FIELD;
}
else if (last == HOUR0_FIELD)
{
minute = val;
last = MINUTE_FIELD;
}
else if (last == MINUTE_FIELD)
{
second = val;
last = SECOND_FIELD;
}
else if (lastsep == '.')
{
; // This is milliseconds or something. Ignore it
last = WEEK_OF_YEAR_FIELD; // Just a random value
}
else // It is year. I have spoken!
{
year = processYear(val);
last = YEAR_FIELD;
}
}
}
private int parseLeadingZeros(String dateStr, ParsePosition pos,
FieldSizePair p)
{
int value;
int index = pos.getIndex(); int index = pos.getIndex();
String buf = null; boolean found_zone = false;
for (int j = 0; j < zoneCount; j++)
if (p.size == 1)
{
char c = dateStr.charAt(index+1);
if ((dateStr.charAt(index) == '1') &&
Character.isDigit(dateStr.charAt(index+1)))
buf = dateStr.substring(index, index+2);
else
buf = dateStr.substring(index, index+1);
pos.setIndex(index + buf.length());
}
else if (p.size == 2)
{ {
buf = dateStr.substring(index, index+2); String[] strings = zoneStrings[j];
pos.setIndex(index+2); int k;
} for (k = 1; k < strings.length; ++k)
else if (p.size == 3)
{ {
buf = dateStr.substring(index, index+3); if (dateStr.startsWith(strings[k], index))
pos.setIndex(index+3); break;
}
else
{
buf = dateStr.substring(index, index+4);
pos.setIndex(index+4);
}
try
{
value = Integer.parseInt(buf);
} }
catch(NumberFormatException nfe) if (k != strings.length)
{ {
pos.setIndex(index); if (k > 2)
pos.setErrorIndex(index); ; // FIXME: dst.
return -1; zone_number = 0; // FIXME: dst.
// FIXME: raw offset to SimpleTimeZone const.
calendar.setTimeZone(new SimpleTimeZone (1, strings[0]));
pos.setIndex(index + strings[k].length());
break;
} }
return value;
} }
if (! found_zone)
/*
* Note that this method doesn't properly protect against
* StringIndexOutOfBoundsException. FIXME
*/
private Date parseStrict(String dateStr, ParsePosition pos)
{ {
// start looking at position pos.index
Enumeration e = tokens.elements();
Calendar theCalendar = (Calendar) calendar.clone();
theCalendar.clear();
theCalendar.setTime(new Date(0));
int value, index, hour = -1;
String buf;
while (pos.getIndex() < dateStr.length()) {
Object o = e.nextElement();
if (o instanceof FieldSizePair) {
FieldSizePair p = (FieldSizePair) o;
switch (p.field) {
case ERA_FIELD:
value = indexInArray(dateStr,pos.getIndex(),formatData.eras);
if (value == -1) {
pos.setErrorIndex(pos.getIndex()); pos.setErrorIndex(pos.getIndex());
return null; return null;
} }
pos.setIndex(pos.getIndex() + formatData.eras[value].length());
theCalendar.set(Calendar.ERA,value);
break; break;
default:
case YEAR_FIELD:
String y;
if (p.size < 4)
y = dateStr.substring(pos.getIndex(), pos.getIndex() + 2);
else
y = dateStr.substring(pos.getIndex(), pos.getIndex() + 4);
int year;
try
{
year = Integer.parseInt(y);
}
catch(NumberFormatException nfe)
{
pos.setErrorIndex(pos.getIndex()); pos.setErrorIndex(pos.getIndex());
return null; return null;
} }
if (p.size < 4) // Compute the value we should assign to the field.
year += get2DigitYearStart().getYear(); int value;
if (is_numeric)
theCalendar.set(Calendar.YEAR, year);
if (p.size < 4)
pos.setIndex(pos.getIndex()+2);
else
pos.setIndex(pos.getIndex()+4);
break;
case MONTH_FIELD:
if (p.size > 2)
{
index = pos.getIndex();
value = indexInArray(dateStr,pos.getIndex(),
(p.size == 3) ? formatData.shortMonths : formatData.months);
if (value == -1)
{ {
pos.setErrorIndex(pos.getIndex()); numberFormat.setMinimumIntegerDigits(count);
Number n = numberFormat.parse(dateStr, pos);
if (pos == null || ! (n instanceof Long))
return null; return null;
value = n.intValue() + offset;
} }
if (p.size == 3) else if (match != null)
pos.setIndex(index + formatData.shortMonths[value].length());
else
pos.setIndex(index + formatData.months[value].length());
theCalendar.set(Calendar.MONTH, value);
break;
}
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
theCalendar.set(Calendar.MONTH, value);
break;
case DATE_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
theCalendar.set(Calendar.DATE, value);
break;
case HOUR_OF_DAY1_FIELD:
case HOUR_OF_DAY0_FIELD:
index = pos.getIndex();
buf = dateStr.substring(index, index+2);
try
{ {
value = Integer.parseInt(buf); int index = pos.getIndex();
} int i;
catch(NumberFormatException nfe) for (i = offset; i < match.length; ++i)
{ {
return null; if (dateStr.startsWith(match[i], index))
}
if (p.field == HOUR_OF_DAY0_FIELD)
// theCalendar.set(Calendar.HOUR_OF_DAY, value);
hour = value + 1;
else
// theCalendar.set(Calendar.HOUR_OF_DAY, value-1);
hour = value;
pos.setIndex(index+2);
break;
case MINUTE_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
theCalendar.set(Calendar.MINUTE, value);
break;
case SECOND_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
theCalendar.set(Calendar.SECOND, value);
break;
case MILLISECOND_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
theCalendar.set(Calendar.MILLISECOND, value);
break;
case DAY_OF_WEEK_FIELD:
value = indexInArray(dateStr,pos.getIndex(),(p.size < 4) ? formatData.shortWeekdays : formatData.weekdays);
if (value == -1) {
pos.setErrorIndex(pos.getIndex());
return null;
}
pos.setIndex(pos.getIndex() + ((p.size < 4) ? formatData.shortWeekdays[value].length()
: formatData.weekdays[value].length()));
// Note: Calendar.set(Calendar.DAY_OF_WEEK,value) does not work
// as implemented in jdk1.1.5 (possibly DAY_OF_WEEK is meant to
// be read-only). Instead, calculate number of days offset.
theCalendar.add(Calendar.DATE,value
- theCalendar.get(Calendar.DAY_OF_WEEK));
// in JDK, this seems to clear the hours, so we'll do the same.
theCalendar.set(Calendar.HOUR_OF_DAY,0);
break;
case DAY_OF_YEAR_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
theCalendar.set(Calendar.DAY_OF_YEAR, value);
break;
// Just parse and ignore
case DAY_OF_WEEK_IN_MONTH_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
break;
// Just parse and ignore
case WEEK_OF_YEAR_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
break;
// Just parse and ignore
case WEEK_OF_MONTH_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
break;
case AM_PM_FIELD:
value = indexInArray(dateStr,pos.getIndex(),formatData.ampms);
if (value == -1) {
pos.setErrorIndex(pos.getIndex());
return null;
}
pos.setIndex(pos.getIndex() + formatData.ampms[value].length());
theCalendar.set(Calendar.AM_PM,value);
break;
case HOUR1_FIELD:
case HOUR0_FIELD:
value = parseLeadingZeros(dateStr, pos, p);
if (value == -1)
return null;
if (p.field == HOUR1_FIELD)
theCalendar.set(Calendar.HOUR, value);
if (p.field == HOUR0_FIELD)
theCalendar.set(Calendar.HOUR, value+1);
break;
/*
case TIMEZONE_FIELD:
// TODO: FIXME: XXX
break; break;
*/
default:
throw new IllegalArgumentException("Illegal pattern character: " +
p.field);
} // end switch
} else if (o instanceof String) {
String ostr = (String) o;
if (dateStr.substring(pos.getIndex(),pos.getIndex()+ostr.length()).equals(ostr)) {
pos.setIndex(pos.getIndex() + ostr.length());
} else {
pos.setErrorIndex(pos.getIndex());
return null;
} }
} else if (o instanceof Character) { if (i == match.length)
Character ochar = (Character) o; {
if (dateStr.charAt(pos.getIndex()) == ochar.charValue()) { pos.setErrorIndex(index);
pos.setIndex(pos.getIndex() + 1);
} else {
pos.setErrorIndex(pos.getIndex());
return null; return null;
} }
pos.setIndex(index + match[i].length());
value = i;
} }
else
value = zone_number;
// Assign the value and move on.
calendar.set(calendar_field, value);
} }
if (hour != -1) try
{
if (theCalendar.get(Calendar.AM_PM) == Calendar.PM)
{ {
if (hour == 12) return calendar.getTime();
theCalendar.set(Calendar.HOUR_OF_DAY, 12);
else
theCalendar.set(Calendar.HOUR_OF_DAY, hour + 12);
} }
else catch (IllegalArgumentException x)
{ {
if (hour == 12) pos.setErrorIndex(pos.getIndex());
theCalendar.set(Calendar.HOUR_OF_DAY, 0); return null;
else
theCalendar.set(Calendar.HOUR_OF_DAY, hour);
}
}
return theCalendar.getTime();
} }
/**
* This method parses the specified string into a date.
*
* @param dateStr The date string to parse.
* @param pos The input and output parse position
*
* @return The parsed date, or <code>null</code> if the string cannot be
* parsed.
*/
public Date parse(String dateStr, ParsePosition pos) {
if (isLenient())
return parseLenient(dateStr, pos);
else
return parseStrict(dateStr, pos);
} }
} }
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -15,6 +15,7 @@ details. */ ...@@ -15,6 +15,7 @@ details. */
#include <gcj/cni.h> #include <gcj/cni.h>
#include <java/util/TimeZone.h> #include <java/util/TimeZone.h>
#include <java/util/GregorianCalendar.h> #include <java/util/GregorianCalendar.h>
#include <java/lang/IllegalArgumentException.h>
#include <time.h> #include <time.h>
void void
...@@ -27,11 +28,52 @@ java::util::GregorianCalendar::computeTime () ...@@ -27,11 +28,52 @@ java::util::GregorianCalendar::computeTime ()
tim.tm_mday = elements(fields)[DATE]; tim.tm_mday = elements(fields)[DATE];
tim.tm_mon = elements(fields)[MONTH]; tim.tm_mon = elements(fields)[MONTH];
tim.tm_year = elements(fields)[YEAR] - 1900; tim.tm_year = elements(fields)[YEAR] - 1900;
tim.tm_isdst = 0; // FIXME tim.tm_isdst = 0;
#ifndef ECOS #ifndef ECOS
// FIXME: None of the standard C library access to the ECOS calendar // FIXME: None of the standard C library access to the ECOS calendar
// is yet available. // is yet available.
time_t t = mktime (&tim); time_t t = mktime (&tim);
if (!isLenient ())
{
// mktime will correct for any time leniencies (e.g. 31-Apr becomes
// 1-May).
// Daylight savings time is a special case since times in hour 23
// will compute to hour 0 of the next day.
if (tim.tm_isdst == 0 || elements(fields)[HOUR_OF_DAY] != 23)
{
if (tim.tm_sec != elements(fields)[SECOND] ||
tim.tm_min != elements(fields)[MINUTE] ||
tim.tm_hour != elements(fields)[HOUR_OF_DAY] +
(tim.tm_isdst > 0 ? 1 : 0) ||
tim.tm_mday != elements(fields)[DATE] ||
tim.tm_mon != elements(fields)[MONTH] ||
tim.tm_year != elements(fields)[YEAR] - 1900)
throw new java::lang::IllegalArgumentException ();
}
else
{
// The easiest thing to do is to temporarily shift the clock
// back from the 23th hour so mktime doesn't cause the extra
// hour for DST to roll the date to the next day.
struct tm tmp_tim;
tmp_tim.tm_sec = elements(fields)[SECOND];
tmp_tim.tm_min = elements(fields)[MINUTE];
tmp_tim.tm_hour = elements(fields)[HOUR_OF_DAY] - 1;
tmp_tim.tm_mday = elements(fields)[DATE];
tmp_tim.tm_mon = elements(fields)[MONTH];
tmp_tim.tm_year = elements(fields)[YEAR] - 1900;
tmp_tim.tm_isdst = 0;
mktime (&tmp_tim);
if (tmp_tim.tm_sec != elements(fields)[SECOND] ||
tmp_tim.tm_min != elements(fields)[MINUTE] ||
tmp_tim.tm_hour != elements(fields)[HOUR_OF_DAY] ||
tmp_tim.tm_mday != elements(fields)[DATE] ||
tmp_tim.tm_mon != elements(fields)[MONTH] ||
tmp_tim.tm_year != elements(fields)[YEAR] - 1900)
throw new java::lang::IllegalArgumentException ();
}
}
#else #else
time_t t = 0; time_t t = 0;
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment