Commit 5814ecc2 by Per Bothner Committed by Per Bothner

Date.java (parse): Fix a number of problems.


	* java/util/Date.java (parse):  Fix a number of problems.
	(skipParens):  Remove no-longer-needed method.

From-SVN: r75381
parent e237c8f5
2004-01-03 Per Bothner <per@bothner.com>
* java/util/Date.java (parse): Fix a number of problems.
(skipParens): Remove no-longer-needed method.
2003-12-31 Michael Koch <konqueror@gmx.de> 2003-12-31 Michael Koch <konqueror@gmx.de>
* gnu/java/net/protocol/http/Connection.java * gnu/java/net/protocol/http/Connection.java
......
...@@ -304,34 +304,6 @@ public class Date implements Cloneable, Comparable, java.io.Serializable ...@@ -304,34 +304,6 @@ public class Date implements Cloneable, Comparable, java.io.Serializable
return format.format(this); return format.format(this);
} }
private static int skipParens(String string, int offset)
{
int len = string.length();
int p = 0;
int i;
for (i = offset; i < len; ++i)
{
if (string.charAt(i) == '(')
++p;
else if (string.charAt(i) == ')')
{
--p;
if (p == 0)
return i + 1;
// If we've encounted unbalanced parens, just return the
// leftover one as an ordinary character. It will be
// caught later in parsing and cause an
// IllegalArgumentException.
if (p < 0)
return i;
}
}
// Not sure what to do if `p != 0' here.
return i;
}
private static int parseTz(String tok, char sign) private static int parseTz(String tok, char sign)
throws IllegalArgumentException throws IllegalArgumentException
{ {
...@@ -408,20 +380,25 @@ public class Date implements Cloneable, Comparable, java.io.Serializable ...@@ -408,20 +380,25 @@ public class Date implements Cloneable, Comparable, java.io.Serializable
// Trim out any nested stuff in parentheses now to make parsing easier. // Trim out any nested stuff in parentheses now to make parsing easier.
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
int off = 0; int parenNesting = 0;
int openParenOffset, tmpMonth; int len = string.length();
while ((openParenOffset = string.indexOf('(', off)) >= 0) for (int i = 0; i < len; i++)
{ {
// Copy part of string leading up to open paren. char ch = string.charAt(i);
buf.append(string.substring(off, openParenOffset)); if (ch >= 'a' && ch <= 'z')
off = skipParens(string, openParenOffset); ch -= 'a' - 'A';
if (ch == '(')
parenNesting++;
else if (parenNesting == 0)
buf.append(ch);
else if (ch == ')')
parenNesting--;
} }
buf.append(string.substring(off)); int tmpMonth;
// Make all chars upper case to simplify comparisons later. // Make all chars upper case to simplify comparisons later.
// Also ignore commas; treat them as delimiters. // Also ignore commas; treat them as delimiters.
StringTokenizer strtok = StringTokenizer strtok = new StringTokenizer(buf.toString(), " \t\n\r,");
new StringTokenizer(buf.toString().toUpperCase(), " \t\n\r,");
while (strtok.hasMoreTokens()) while (strtok.hasMoreTokens())
{ {
...@@ -436,56 +413,59 @@ public class Date implements Cloneable, Comparable, java.io.Serializable ...@@ -436,56 +413,59 @@ public class Date implements Cloneable, Comparable, java.io.Serializable
{ {
while (tok != null && tok.length() > 0) while (tok != null && tok.length() > 0)
{ {
// A colon or slash may be valid in the number. int punctOffset = tok.length();
// Find the first of these before calling parseInt. int num = 0;
int colon = tok.indexOf(':'); int punct;
int slash = tok.indexOf('/'); for (int i = 0; ; i++)
int hyphen = tok.indexOf('-'); {
// We choose tok.length initially because it makes if (i >= punctOffset)
// processing simpler. {
int punctOffset = tok.length(); punct = -1;
if (colon >= 0) break;
punctOffset = Math.min(punctOffset, colon); }
if (slash >= 0) else
punctOffset = Math.min(punctOffset, slash); {
if (hyphen >= 0) punct = tok.charAt(i);
punctOffset = Math.min(punctOffset, hyphen); if (punct >= '0' && punct <= '9')
// Following code relies on -1 being the exceptional {
// case. if (num > 999999999) // in case of overflow
if (punctOffset == tok.length()) throw new IllegalArgumentException(tok);
punctOffset = -1; num = 10 * num + (punct - '0');
}
int num; else
try {
{ punctOffset = i;
num = Integer.parseInt(punctOffset < 0 ? tok : break;
tok.substring(0, punctOffset)); }
} }
catch (NumberFormatException ex)
{ }
throw new IllegalArgumentException(tok);
} if (punct == ':')
// TBD: Spec says year can be followed by a slash. That might
// make sense if using YY/MM/DD formats, but it would fail in
// that format for years <= 70. Also, what about 1900? That
// is interpreted as the year 3800; seems that the comparison
// should be num >= 1900 rather than just > 1900.
// What about a year of 62 - 70? (61 or less could be a (leap)
// second). 70/MM/DD cause an exception but 71/MM/DD is ok
// even though there's no ambiguity in either case.
// For the parse method, the spec as written seems too loose.
// Until shown otherwise, we'll follow the spec as written.
if (num > 70 && (punctOffset < 0 || punctOffset == slash))
year = num > 1900 ? num - 1900 : num;
else if (punctOffset > 0 && punctOffset == colon)
{ {
if (hour < 0) if (hour < 0)
hour = num; hour = num;
else else
minute = num; minute = num;
} }
else if (punctOffset > 0 && punctOffset == slash) else if ((num >= 70
&& (punct == ' ' || punct == ','
|| punct == '/' || punct < 0))
|| (num < 70 && day >= 0 && month >= 0 && year < 0))
{
if (num >= 100)
year = num;
else
{
int curYear = 1900 + new Date().getYear();
int firstYear = curYear - 80;
year = firstYear / 100 * 100 + num;
int yx = year;
if (year < firstYear)
year += 100;
}
}
else if (punct == '/')
{ {
if (month < 0) if (month < 0)
month = num - 1; month = num - 1;
...@@ -502,7 +482,7 @@ public class Date implements Cloneable, Comparable, java.io.Serializable ...@@ -502,7 +482,7 @@ public class Date implements Cloneable, Comparable, java.io.Serializable
throw new IllegalArgumentException(tok); throw new IllegalArgumentException(tok);
// Advance string if there's more to process in this token. // Advance string if there's more to process in this token.
if (punctOffset < 0 || punctOffset + 1 >= tok.length()) if (punct < 0 || punctOffset + 1 >= tok.length())
tok = null; tok = null;
else else
tok = tok.substring(punctOffset + 1); tok = tok.substring(punctOffset + 1);
...@@ -573,22 +553,29 @@ public class Date implements Cloneable, Comparable, java.io.Serializable ...@@ -573,22 +553,29 @@ public class Date implements Cloneable, Comparable, java.io.Serializable
throw new IllegalArgumentException(tok); throw new IllegalArgumentException(tok);
} }
// Unspecified minutes and seconds should default to 0. // Unspecified hours, minutes, or seconds should default to 0.
if (hour < 0)
hour = 0;
if (minute < 0) if (minute < 0)
minute = 0; minute = 0;
if (second < 0) if (second < 0)
second = 0; second = 0;
// Throw exception if any other fields have not been recognized and set. // Throw exception if any other fields have not been recognized and set.
if (year < 0 || month < 0 || day < 0 || hour < 0) if (year < 0 || month < 0 || day < 0)
throw new IllegalArgumentException("Missing field"); throw new IllegalArgumentException("Missing field");
// Return the time in either local time or relative to GMT as parsed. // Return the time in either local time or relative to GMT as parsed.
// If no time-zone was specified, get the local one (in minutes) and // If no time-zone was specified, get the local one (in minutes) and
// convert to milliseconds before adding to the UTC. // convert to milliseconds before adding to the UTC.
return UTC(year, month, day, hour, minute, second) + (localTimezone ? GregorianCalendar cal
new Date(year, month, day).getTimezoneOffset() * 60 * 1000: = new GregorianCalendar(year, month, day, hour, minute, second);
-timezone * 60 * 1000); if (!localTimezone)
{
cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000);
cal.set(Calendar.DST_OFFSET, 0);
}
return cal.getTimeInMillis();
} }
/** /**
......
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