re PR libgcj/17002 (java.util.TimeZone.getDefault() is broken)
libjava/
PR libgcj/17002
PR classpath/28550
* java/util/VMTimeZone.java (getDefaultTimeZoneId): To read
/etc/localtime, use ZoneInfo.readTZFile instead of
VMTimeZone.readtzFile. Get better timezone name for /etc/localtime,
either if it is a symlink or through /etc/sysconfig/clock.
(readSysconfigClockFile): New static method.
(readtzFile): Removed.
* java/lang/System.java: Add gnu.java.util.zoneinfo.dir to comments.
* posix.cc (_Jv_platform_initProperties): Set
gnu.java.util.zoneinfo.dir.
* sources.am (gnu_java_util_source_files): Add
classpath/gnu/java/util/ZoneInfo.java.
* Makefile.in: Regenerated.
* java/util/VMTimeZone.h: Regenerated.
* java/util/TimeZone.h: Regenerated.
* gnu/java/util/ZoneInfo.h: Generated.
libjava/classpath/
* java/util/Date.java (parse): Properly parse 09:01:02 as
hours/minutes/seconds, not as hours/minutes/year.
* java/util/SimpleTimeZone.java (SimpleTimeZone): Simplify
{start,end}TimeMode constructor by calling shorter constructor,
set {start,end}TimeMode fields after it returns.
(setStartRule): Don't adjust startTime into WALL_TIME. Set
startTimeMode to WALL_TIME.
(endStartRule): Similarly.
(getOffset): Handle properly millis + dstOffset overflowing into the
next day. Adjust startTime resp. endTime based on startTimeMode
resp. endTimeMode.
* java/util/TimeZone.java (zoneinfo_dir, availableIDs, aliases0): New
static fields.
(timezones): Remove synchronized keyword. Set zoneinfo_dir.
If non-null, set up aliases0 and don't put anything into
timezones0.
(defaultZone): Call getTimeZone instead of timezones().get.
(getDefaultTimeZone): Fix parsing of EST5 or EST5EDT6. Use
getTimeZoneInternal instead of timezones().get.
(parseTime): Parse correctly hour:minute.
(getTimeZoneInternal): New private method.
(getTimeZone): Do the custom ID checking first, canonicalize
ID for custom IDs as required by documentation. Call
getTimeZoneInternal to handle the rest.
(getAvailableIDs(int)): Add locking. Handle zoneinfo_dir != null.
(getAvailableIDs(File,String,ArrayList)): New private method.
(getAvailableIDs()): Add locking. Handle zoneinfo_dir != null.
* gnu/java/util/ZoneInfo.java: New file.
From-SVN: r122229
This commit is contained in:
committed by
Jakub Jelinek
parent
0c5c188f07
commit
b3502aa8d4
@@ -754,6 +754,7 @@ public class Date
|
||||
}
|
||||
else if (firstch >= '0' && firstch <= '9')
|
||||
{
|
||||
int lastPunct = -1;
|
||||
while (tok != null && tok.length() > 0)
|
||||
{
|
||||
int punctOffset = tok.length();
|
||||
@@ -791,6 +792,13 @@ public class Date
|
||||
else
|
||||
minute = num;
|
||||
}
|
||||
else if (lastPunct == ':' && hour >= 0 && (minute < 0 || second < 0))
|
||||
{
|
||||
if (minute < 0)
|
||||
minute = num;
|
||||
else
|
||||
second = num;
|
||||
}
|
||||
else if ((num >= 70
|
||||
&& (punct == ' ' || punct == ','
|
||||
|| punct == '/' || punct < 0))
|
||||
@@ -828,6 +836,7 @@ public class Date
|
||||
tok = null;
|
||||
else
|
||||
tok = tok.substring(punctOffset + 1);
|
||||
lastPunct = punct;
|
||||
}
|
||||
}
|
||||
else if (firstch >= 'A' && firstch <= 'Z')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* java.util.SimpleTimeZone
|
||||
Copyright (C) 1998, 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2000, 2003, 2004, 2005, 2007
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -141,8 +142,8 @@ public class SimpleTimeZone extends TimeZone
|
||||
|
||||
/**
|
||||
* This variable specifies the time of change to daylight savings.
|
||||
* This time is given in milliseconds after midnight local
|
||||
* standard time.
|
||||
* This time is given in milliseconds after midnight in startTimeMode
|
||||
* chosen time mode.
|
||||
* @serial
|
||||
*/
|
||||
private int startTime;
|
||||
@@ -187,8 +188,8 @@ public class SimpleTimeZone extends TimeZone
|
||||
|
||||
/**
|
||||
* This variable specifies the time of change back to standard time.
|
||||
* This time is given in milliseconds after midnight local
|
||||
* standard time.
|
||||
* This time is given in milliseconds after midnight in endTimeMode
|
||||
* chosen time mode.
|
||||
* @serial
|
||||
*/
|
||||
private int endTime;
|
||||
@@ -380,24 +381,17 @@ public class SimpleTimeZone extends TimeZone
|
||||
int endDayOfWeekInMonth, int endDayOfWeek,
|
||||
int endTime, int endTimeMode, int dstSavings)
|
||||
{
|
||||
this.rawOffset = rawOffset;
|
||||
setID(id);
|
||||
useDaylight = true;
|
||||
this(rawOffset, id, startMonth, startDayOfWeekInMonth, startDayOfWeek,
|
||||
startTime, endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
|
||||
|
||||
if (startTimeMode < WALL_TIME || startTimeMode > UTC_TIME)
|
||||
throw new IllegalArgumentException("startTimeMode must be one of WALL_TIME, STANDARD_TIME, or UTC_TIME");
|
||||
if (endTimeMode < WALL_TIME || endTimeMode > UTC_TIME)
|
||||
throw new IllegalArgumentException("endTimeMode must be one of WALL_TIME, STANDARD_TIME, or UTC_TIME");
|
||||
this.startTimeMode = startTimeMode;
|
||||
this.endTimeMode = endTimeMode;
|
||||
|
||||
setStartRule(startMonth, startDayOfWeekInMonth, startDayOfWeek, startTime);
|
||||
setEndRule(endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
|
||||
if (startMonth == endMonth)
|
||||
throw new IllegalArgumentException("startMonth and endMonth must be different");
|
||||
this.startYear = 0;
|
||||
|
||||
this.dstSavings = dstSavings;
|
||||
this.startTimeMode = startTimeMode;
|
||||
this.endTimeMode = endTimeMode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,12 +471,8 @@ public class SimpleTimeZone extends TimeZone
|
||||
this.startMonth = month;
|
||||
this.startDay = day;
|
||||
this.startDayOfWeek = Math.abs(dayOfWeek);
|
||||
if (this.startTimeMode == WALL_TIME || this.startTimeMode == STANDARD_TIME)
|
||||
this.startTime = time;
|
||||
else
|
||||
// Convert from UTC to STANDARD
|
||||
this.startTime = time + this.rawOffset;
|
||||
useDaylight = true;
|
||||
this.startTime = time;
|
||||
this.startTimeMode = WALL_TIME;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -513,24 +503,10 @@ public class SimpleTimeZone extends TimeZone
|
||||
public void setStartRule(int month, int day, int dayOfWeek, int time,
|
||||
boolean after)
|
||||
{
|
||||
// FIXME: XXX: Validate that checkRule and offset processing work with on
|
||||
// or before mode.
|
||||
this.startDay = after ? Math.abs(day) : -Math.abs(day);
|
||||
this.startDayOfWeek = after ? Math.abs(dayOfWeek) : -Math.abs(dayOfWeek);
|
||||
this.startMode = (dayOfWeek != 0)
|
||||
? (after ? DOW_GE_DOM_MODE : DOW_LE_DOM_MODE)
|
||||
: checkRule(month, day, dayOfWeek);
|
||||
this.startDay = Math.abs(this.startDay);
|
||||
this.startDayOfWeek = Math.abs(this.startDayOfWeek);
|
||||
|
||||
this.startMonth = month;
|
||||
|
||||
if (this.startTimeMode == WALL_TIME || this.startTimeMode == STANDARD_TIME)
|
||||
this.startTime = time;
|
||||
if (after)
|
||||
setStartRule(month, day, -dayOfWeek, time);
|
||||
else
|
||||
// Convert from UTC to STANDARD
|
||||
this.startTime = time + this.rawOffset;
|
||||
useDaylight = true;
|
||||
setStartRule(month, -day, -dayOfWeek, time);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -570,14 +546,8 @@ public class SimpleTimeZone extends TimeZone
|
||||
this.endMonth = month;
|
||||
this.endDay = day;
|
||||
this.endDayOfWeek = Math.abs(dayOfWeek);
|
||||
if (this.endTimeMode == WALL_TIME)
|
||||
this.endTime = time;
|
||||
else if (this.endTimeMode == STANDARD_TIME)
|
||||
// Convert from STANDARD to DST
|
||||
this.endTime = time + this.dstSavings;
|
||||
else
|
||||
// Convert from UTC to DST
|
||||
this.endTime = time + this.rawOffset + this.dstSavings;
|
||||
this.endTime = time;
|
||||
this.endTimeMode = WALL_TIME;
|
||||
useDaylight = true;
|
||||
}
|
||||
|
||||
@@ -607,27 +577,10 @@ public class SimpleTimeZone extends TimeZone
|
||||
public void setEndRule(int month, int day, int dayOfWeek, int time,
|
||||
boolean after)
|
||||
{
|
||||
// FIXME: XXX: Validate that checkRule and offset processing work with on
|
||||
// or before mode.
|
||||
this.endDay = after ? Math.abs(day) : -Math.abs(day);
|
||||
this.endDayOfWeek = after ? Math.abs(dayOfWeek) : -Math.abs(dayOfWeek);
|
||||
this.endMode = (dayOfWeek != 0)
|
||||
? (after ? DOW_GE_DOM_MODE : DOW_LE_DOM_MODE)
|
||||
: checkRule(month, day, dayOfWeek);
|
||||
this.endDay = Math.abs(this.endDay);
|
||||
this.endDayOfWeek = Math.abs(endDayOfWeek);
|
||||
|
||||
this.endMonth = month;
|
||||
|
||||
if (this.endTimeMode == WALL_TIME)
|
||||
this.endTime = time;
|
||||
else if (this.endTimeMode == STANDARD_TIME)
|
||||
// Convert from STANDARD to DST
|
||||
this.endTime = time + this.dstSavings;
|
||||
if (after)
|
||||
setEndRule(month, day, -dayOfWeek, time);
|
||||
else
|
||||
// Convert from UTC to DST
|
||||
this.endTime = time + this.rawOffset + this.dstSavings;
|
||||
useDaylight = true;
|
||||
setEndRule(month, -day, -dayOfWeek, time);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -688,16 +641,37 @@ public class SimpleTimeZone extends TimeZone
|
||||
int daylightSavings = 0;
|
||||
if (useDaylight && era == GregorianCalendar.AD && year >= startYear)
|
||||
{
|
||||
int orig_year = year;
|
||||
int time = startTime + (startTimeMode == UTC_TIME ? rawOffset : 0);
|
||||
// This does only work for Gregorian calendars :-(
|
||||
// This is mainly because setStartYear doesn't take an era.
|
||||
boolean afterStart = ! isBefore(year, month, day, dayOfWeek, millis,
|
||||
startMode, startMonth, startDay,
|
||||
startDayOfWeek, startTime);
|
||||
boolean beforeEnd = isBefore(year, month, day, dayOfWeek,
|
||||
millis + dstSavings,
|
||||
endMode, endMonth, endDay, endDayOfWeek,
|
||||
endTime);
|
||||
startDayOfWeek, time);
|
||||
millis += dstSavings;
|
||||
if (millis >= 24 * 60 * 60 * 1000)
|
||||
{
|
||||
millis -= 24 * 60 * 60 * 1000;
|
||||
dayOfWeek = (dayOfWeek % 7) + 1;
|
||||
if (++day > daysInMonth)
|
||||
{
|
||||
day = 1;
|
||||
if (month++ == Calendar.DECEMBER)
|
||||
{
|
||||
month = Calendar.JANUARY;
|
||||
year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
time = endTime + (endTimeMode == UTC_TIME ? rawOffset : 0);
|
||||
if (endTimeMode != WALL_TIME)
|
||||
time += dstSavings;
|
||||
boolean beforeEnd = isBefore(year, month, day, dayOfWeek, millis,
|
||||
endMode, endMonth, endDay, endDayOfWeek,
|
||||
time);
|
||||
|
||||
if (year != orig_year)
|
||||
afterStart = false;
|
||||
if (startMonth < endMonth)
|
||||
// use daylight savings, if the date is after the start of
|
||||
// savings, and before the end of savings.
|
||||
|
||||
@@ -39,6 +39,9 @@ exception statement from your version. */
|
||||
|
||||
package java.util;
|
||||
|
||||
import gnu.classpath.SystemProperties;
|
||||
import gnu.java.util.ZoneInfo;
|
||||
import java.io.File;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.DateFormatSymbols;
|
||||
@@ -115,7 +118,7 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
|
||||
// Fall back on GMT.
|
||||
if (zone == null)
|
||||
zone = (TimeZone) timezones().get("GMT");
|
||||
zone = getTimeZone ("GMT");
|
||||
|
||||
return zone;
|
||||
}
|
||||
@@ -127,6 +130,22 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
|
||||
private static final long serialVersionUID = 3581463369166924961L;
|
||||
|
||||
/**
|
||||
* Flag whether zoneinfo data should be used,
|
||||
* otherwise builtin timezone data will be provided.
|
||||
*/
|
||||
private static String zoneinfo_dir;
|
||||
|
||||
/**
|
||||
* Cached copy of getAvailableIDs().
|
||||
*/
|
||||
private static String[] availableIDs = null;
|
||||
|
||||
/**
|
||||
* JDK 1.1.x compatibility aliases.
|
||||
*/
|
||||
private static HashMap aliases0;
|
||||
|
||||
/**
|
||||
* HashMap for timezones by ID.
|
||||
*/
|
||||
@@ -135,13 +154,55 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
* it is not needed:
|
||||
*/
|
||||
// Package-private to avoid a trampoline.
|
||||
static synchronized HashMap timezones()
|
||||
static HashMap timezones()
|
||||
{
|
||||
if (timezones0 == null)
|
||||
{
|
||||
HashMap timezones = new HashMap();
|
||||
timezones0 = timezones;
|
||||
|
||||
zoneinfo_dir = SystemProperties.getProperty("gnu.java.util.zoneinfo.dir");
|
||||
if (zoneinfo_dir != null && !new File(zoneinfo_dir).isDirectory())
|
||||
zoneinfo_dir = null;
|
||||
|
||||
if (zoneinfo_dir != null)
|
||||
{
|
||||
aliases0 = new HashMap();
|
||||
|
||||
// These deprecated aliases for JDK 1.1.x compatibility
|
||||
// should take precedence over data files read from
|
||||
// /usr/share/zoneinfo.
|
||||
aliases0.put("ACT", "Australia/Darwin");
|
||||
aliases0.put("AET", "Australia/Sydney");
|
||||
aliases0.put("AGT", "America/Argentina/Buenos_Aires");
|
||||
aliases0.put("ART", "Africa/Cairo");
|
||||
aliases0.put("AST", "America/Juneau");
|
||||
aliases0.put("BST", "Asia/Colombo");
|
||||
aliases0.put("CAT", "Africa/Gaborone");
|
||||
aliases0.put("CNT", "America/St_Johns");
|
||||
aliases0.put("CST", "CST6CDT");
|
||||
aliases0.put("CTT", "Asia/Brunei");
|
||||
aliases0.put("EAT", "Indian/Comoro");
|
||||
aliases0.put("ECT", "CET");
|
||||
aliases0.put("EST", "EST5EDT");
|
||||
aliases0.put("EST5", "EST5EDT");
|
||||
aliases0.put("IET", "EST5EDT");
|
||||
aliases0.put("IST", "Asia/Calcutta");
|
||||
aliases0.put("JST", "Asia/Seoul");
|
||||
aliases0.put("MIT", "Pacific/Niue");
|
||||
aliases0.put("MST", "MST7MDT");
|
||||
aliases0.put("MST7", "MST7MDT");
|
||||
aliases0.put("NET", "Indian/Mauritius");
|
||||
aliases0.put("NST", "Pacific/Auckland");
|
||||
aliases0.put("PLT", "Indian/Kerguelen");
|
||||
aliases0.put("PNT", "MST7MDT");
|
||||
aliases0.put("PRT", "America/Anguilla");
|
||||
aliases0.put("PST", "PST8PDT");
|
||||
aliases0.put("SST", "Pacific/Ponape");
|
||||
aliases0.put("VST", "Asia/Bangkok");
|
||||
return timezones;
|
||||
}
|
||||
|
||||
TimeZone tz;
|
||||
// Automatically generated by scripts/timezones.pl
|
||||
// XXX - Should we read this data from a file?
|
||||
@@ -887,7 +948,6 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
static TimeZone getDefaultTimeZone(String sysTimeZoneId)
|
||||
{
|
||||
String stdName = null;
|
||||
String dstName;
|
||||
int stdOffs;
|
||||
int dstOffs;
|
||||
try
|
||||
@@ -900,14 +960,14 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
|
||||
// get std
|
||||
do
|
||||
c = sysTimeZoneId.charAt(index++);
|
||||
c = sysTimeZoneId.charAt(index);
|
||||
while (c != '+' && c != '-' && c != ',' && c != ':'
|
||||
&& ! Character.isDigit(c) && c != '\0' && index < idLength);
|
||||
&& ! Character.isDigit(c) && c != '\0' && ++index < idLength);
|
||||
|
||||
if (index >= idLength)
|
||||
return (TimeZone)timezones().get(sysTimeZoneId);
|
||||
return getTimeZoneInternal(sysTimeZoneId);
|
||||
|
||||
stdName = sysTimeZoneId.substring(0, --index);
|
||||
stdName = sysTimeZoneId.substring(0, index);
|
||||
prevIndex = index;
|
||||
|
||||
// get the std offset
|
||||
@@ -938,7 +998,7 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
if (index >= idLength)
|
||||
{
|
||||
// Do we have an existing timezone with that name and offset?
|
||||
TimeZone tz = (TimeZone) timezones().get(stdName);
|
||||
TimeZone tz = getTimeZoneInternal(stdName);
|
||||
if (tz != null)
|
||||
if (tz.getRawOffset() == stdOffs)
|
||||
return tz;
|
||||
@@ -949,16 +1009,16 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
|
||||
// get dst
|
||||
do
|
||||
c = sysTimeZoneId.charAt(index++);
|
||||
c = sysTimeZoneId.charAt(index);
|
||||
while (c != '+' && c != '-' && c != ',' && c != ':'
|
||||
&& ! Character.isDigit(c) && c != '\0' && index < idLength);
|
||||
&& ! Character.isDigit(c) && c != '\0' && ++index < idLength);
|
||||
|
||||
// Done yet? (Format: std offset dst)
|
||||
if (index >= idLength)
|
||||
{
|
||||
// Do we have an existing timezone with that name and offset
|
||||
// which has DST?
|
||||
TimeZone tz = (TimeZone) timezones().get(stdName);
|
||||
TimeZone tz = getTimeZoneInternal(stdName);
|
||||
if (tz != null)
|
||||
if (tz.getRawOffset() == stdOffs && tz.useDaylightTime())
|
||||
return tz;
|
||||
@@ -968,7 +1028,6 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
}
|
||||
|
||||
// get the dst offset
|
||||
dstName = sysTimeZoneId.substring(prevIndex, --index);
|
||||
prevIndex = index;
|
||||
do
|
||||
c = sysTimeZoneId.charAt(index++);
|
||||
@@ -1005,7 +1064,7 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
if (index >= idLength)
|
||||
{
|
||||
// Time Zone existing with same name, dst and offsets?
|
||||
TimeZone tz = (TimeZone) timezones().get(stdName);
|
||||
TimeZone tz = getTimeZoneInternal(stdName);
|
||||
if (tz != null)
|
||||
if (tz.getRawOffset() == stdOffs && tz.useDaylightTime()
|
||||
&& tz.getDSTSavings() == (dstOffs - stdOffs))
|
||||
@@ -1171,10 +1230,10 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
break;
|
||||
else
|
||||
i++;
|
||||
millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i));
|
||||
if (i >= time.length())
|
||||
return millis;
|
||||
|
||||
millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i));
|
||||
millis += 1000 * Integer.parseInt(time.substring(++i));
|
||||
return millis;
|
||||
}
|
||||
@@ -1406,30 +1465,67 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
* @return The time zone for the identifier or GMT, if no such time
|
||||
* zone exists.
|
||||
*/
|
||||
// FIXME: XXX: JCL indicates this and other methods are synchronized.
|
||||
public static TimeZone getTimeZone(String ID)
|
||||
private static TimeZone getTimeZoneInternal(String ID)
|
||||
{
|
||||
// First check timezones hash
|
||||
TimeZone tz = (TimeZone) timezones().get(ID);
|
||||
if (tz != null)
|
||||
TimeZone tz = null;
|
||||
TimeZone tznew = null;
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
if (tz.getID().equals(ID))
|
||||
return tz;
|
||||
synchronized (TimeZone.class)
|
||||
{
|
||||
tz = (TimeZone) timezones().get(ID);
|
||||
if (tz != null)
|
||||
{
|
||||
if (!tz.getID().equals(ID))
|
||||
{
|
||||
// We always return a timezone with the requested ID.
|
||||
// This is the same behaviour as with JDK1.2.
|
||||
tz = (TimeZone) tz.clone();
|
||||
tz.setID(ID);
|
||||
// We also save the alias, so that we return the same
|
||||
// object again if getTimeZone is called with the same
|
||||
// alias.
|
||||
timezones().put(ID, tz);
|
||||
}
|
||||
return tz;
|
||||
}
|
||||
else if (tznew != null)
|
||||
{
|
||||
timezones().put(ID, tznew);
|
||||
return tznew;
|
||||
}
|
||||
}
|
||||
|
||||
// We always return a timezone with the requested ID.
|
||||
// This is the same behaviour as with JDK1.2.
|
||||
tz = (TimeZone) tz.clone();
|
||||
tz.setID(ID);
|
||||
// We also save the alias, so that we return the same
|
||||
// object again if getTimeZone is called with the same
|
||||
// alias.
|
||||
timezones().put(ID, tz);
|
||||
return tz;
|
||||
if (pass == 1 || zoneinfo_dir == null)
|
||||
return null;
|
||||
|
||||
// aliases0 is never changing after first timezones(), so should
|
||||
// be safe without synchronization.
|
||||
String zonename = (String) aliases0.get(ID);
|
||||
if (zonename == null)
|
||||
zonename = ID;
|
||||
|
||||
// Read the file outside of the critical section, it is expensive.
|
||||
tznew = ZoneInfo.readTZFile (ID, zoneinfo_dir
|
||||
+ File.separatorChar + zonename);
|
||||
if (tznew == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
// See if the ID is really a GMT offset form.
|
||||
// Note that GMT is in the table so we know it is different.
|
||||
if (ID.startsWith("GMT"))
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TimeZone for the given ID.
|
||||
* @param ID the time zone identifier.
|
||||
* @return The time zone for the identifier or GMT, if no such time
|
||||
* zone exists.
|
||||
*/
|
||||
public static TimeZone getTimeZone(String ID)
|
||||
{
|
||||
// Check for custom IDs first
|
||||
if (ID.startsWith("GMT") && ID.length() > 3)
|
||||
{
|
||||
int pos = 3;
|
||||
int offset_direction = 1;
|
||||
@@ -1474,8 +1570,20 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
}
|
||||
}
|
||||
|
||||
return new SimpleTimeZone((hour * (60 * 60 * 1000) +
|
||||
minute * (60 * 1000))
|
||||
// Custom IDs have to be normalized
|
||||
StringBuffer sb = new StringBuffer(9);
|
||||
sb.append("GMT");
|
||||
|
||||
sb.append(offset_direction >= 0 ? '+' : '-');
|
||||
sb.append((char) ('0' + hour / 10));
|
||||
sb.append((char) ('0' + hour % 10));
|
||||
sb.append(':');
|
||||
sb.append((char) ('0' + minute / 10));
|
||||
sb.append((char) ('0' + minute % 10));
|
||||
ID = sb.toString();
|
||||
|
||||
return new SimpleTimeZone((hour * (60 * 60 * 1000)
|
||||
+ minute * (60 * 1000))
|
||||
* offset_direction, ID);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
@@ -1483,8 +1591,11 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, return GMT per spec
|
||||
return getTimeZone("GMT");
|
||||
TimeZone tz = getTimeZoneInternal(ID);
|
||||
if (tz != null)
|
||||
return tz;
|
||||
|
||||
return new SimpleTimeZone(0, "GMT");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1497,37 +1608,134 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
|
||||
*/
|
||||
public static String[] getAvailableIDs(int rawOffset)
|
||||
{
|
||||
int count = 0;
|
||||
Iterator iter = timezones().entrySet().iterator();
|
||||
while (iter.hasNext())
|
||||
synchronized (TimeZone.class)
|
||||
{
|
||||
// Don't iterate the values, since we want to count
|
||||
// doubled values (aliases)
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
|
||||
count++;
|
||||
HashMap h = timezones();
|
||||
int count = 0;
|
||||
if (zoneinfo_dir == null)
|
||||
{
|
||||
Iterator iter = h.entrySet().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
// Don't iterate the values, since we want to count
|
||||
// doubled values (aliases)
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
|
||||
count++;
|
||||
}
|
||||
|
||||
String[] ids = new String[count];
|
||||
count = 0;
|
||||
iter = h.entrySet().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
|
||||
ids[count++] = (String) entry.getKey();
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
||||
String[] s = getAvailableIDs();
|
||||
int count = 0;
|
||||
for (int i = 0; i < s.length; i++)
|
||||
{
|
||||
TimeZone t = getTimeZoneInternal(s[i]);
|
||||
if (t == null || t.getRawOffset() != rawOffset)
|
||||
s[i] = null;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
String[] ids = new String[count];
|
||||
count = 0;
|
||||
iter = timezones().entrySet().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
|
||||
ids[count++] = (String) entry.getKey();
|
||||
}
|
||||
for (int i = 0; i < s.length; i++)
|
||||
if (s[i] != null)
|
||||
ids[count++] = s[i];
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
private static int getAvailableIDs(File d, String prefix, ArrayList list)
|
||||
{
|
||||
String[] files = d.list();
|
||||
int count = files.length;
|
||||
boolean top = prefix.length() == 0;
|
||||
list.add (files);
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{
|
||||
if (top
|
||||
&& (files[i].equals("posix")
|
||||
|| files[i].equals("right")
|
||||
|| files[i].endsWith(".tab")
|
||||
|| aliases0.get(files[i]) != null))
|
||||
{
|
||||
files[i] = null;
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
File f = new File(d, files[i]);
|
||||
if (f.isDirectory())
|
||||
{
|
||||
count += getAvailableIDs(f, prefix + files[i]
|
||||
+ File.separatorChar, list) - 1;
|
||||
files[i] = null;
|
||||
}
|
||||
else
|
||||
files[i] = prefix + files[i];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all available IDs.
|
||||
* @return An array of all supported IDs.
|
||||
*/
|
||||
public static String[] getAvailableIDs()
|
||||
{
|
||||
return (String[])
|
||||
timezones().keySet().toArray(new String[timezones().size()]);
|
||||
synchronized (TimeZone.class)
|
||||
{
|
||||
HashMap h = timezones();
|
||||
if (zoneinfo_dir == null)
|
||||
return (String[]) h.keySet().toArray(new String[h.size()]);
|
||||
|
||||
if (availableIDs != null)
|
||||
{
|
||||
String[] ids = new String[availableIDs.length];
|
||||
for (int i = 0; i < availableIDs.length; i++)
|
||||
ids[i] = availableIDs[i];
|
||||
return ids;
|
||||
}
|
||||
|
||||
File d = new File(zoneinfo_dir);
|
||||
ArrayList list = new ArrayList(30);
|
||||
int count = getAvailableIDs(d, "", list) + aliases0.size();
|
||||
availableIDs = new String[count];
|
||||
String[] ids = new String[count];
|
||||
|
||||
count = 0;
|
||||
for (int i = 0; i < list.size(); i++)
|
||||
{
|
||||
String[] s = (String[]) list.get(i);
|
||||
for (int j = 0; j < s.length; j++)
|
||||
if (s[j] != null)
|
||||
{
|
||||
availableIDs[count] = s[j];
|
||||
ids[count++] = s[j];
|
||||
}
|
||||
}
|
||||
|
||||
Iterator iter = aliases0.entrySet().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
availableIDs[count] = (String) entry.getKey();
|
||||
ids[count++] = (String) entry.getKey();
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user