+2004-09-25 Mark Wielaard <mark@klomp.org>
+
+ * Makefile.am (core_java_source_files): Add VMTimeZone.java.
+ (nat_source_files): Rename natTimeZone.cc to natVMTimeZone.cc.
+ * Makefile.in: Regenerated.
+
+ * gcj/javaprims.h: Regenerated.
+
+ * java/util/TimeZone.java (defaultZone): Use VMTimeZone.
+ (getDefaultTimeZone): Make package private. Check that GMToffset
+ contains at least one digit.
+ (getDefaultTimeZoneId, readTimeZoneFile, readtzFile): (Re)Moved to
+ VMTimeZone.
+ * util/VMTimeZone.java: New file with above methods.
+
+ * java/util/natTimeZone.cc: Removed (renamed).
+ * java/util/natVMTimeZone.cc: Added (renamed).
+
+2004-09-25 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/util/TimeZone.java
+ (getDefaultTimeZone): Fixed test to distinguish between hours and
+ minutes in specified timezone.
+
2004-09-25 Jeroen Frijters <jeroen@frijters.net>
* java/lang/reflect/Proxy.java (getPackage, ClassFactory): Fixed
java/util/TreeSet.java \
java/util/TooManyListenersException.java \
java/util/Vector.java \
+java/util/VMTimeZone.java \
java/util/WeakHashMap.java \
java/util/logging/ConsoleHandler.java \
java/util/logging/ErrorManager.java \
java/nio/natDirectByteBufferImpl.cc \
java/text/natCollator.cc \
java/util/natResourceBundle.cc \
-java/util/natTimeZone.cc \
+java/util/natVMTimeZone.cc \
java/util/zip/natDeflater.cc \
java/util/zip/natInflater.cc
java/lang/reflect/natProxy.cc java/net/natNetworkInterface.cc \
java/net/natInetAddress.cc java/nio/channels/natChannels.cc \
java/nio/natDirectByteBufferImpl.cc java/text/natCollator.cc \
- java/util/natResourceBundle.cc java/util/natTimeZone.cc \
+ java/util/natResourceBundle.cc java/util/natVMTimeZone.cc \
java/util/zip/natDeflater.cc java/util/zip/natInflater.cc \
java/lang/dtoa.c java/lang/k_rem_pio2.c java/lang/s_tan.c \
java/lang/e_acos.c java/lang/k_sin.c java/lang/strtod.c \
java/util/TimerTask.java java/util/TreeMap.java \
java/util/TreeSet.java \
java/util/TooManyListenersException.java java/util/Vector.java \
- java/util/WeakHashMap.java \
+ java/util/VMTimeZone.java java/util/WeakHashMap.java \
java/util/logging/ConsoleHandler.java \
java/util/logging/ErrorManager.java \
java/util/logging/FileHandler.java \
java/lang/reflect/natProxy.lo java/net/natNetworkInterface.lo \
java/net/natInetAddress.lo java/nio/channels/natChannels.lo \
java/nio/natDirectByteBufferImpl.lo java/text/natCollator.lo \
- java/util/natResourceBundle.lo java/util/natTimeZone.lo \
+ java/util/natResourceBundle.lo java/util/natVMTimeZone.lo \
java/util/zip/natDeflater.lo java/util/zip/natInflater.lo
am__objects_7 = java/lang/dtoa.lo java/lang/k_rem_pio2.lo \
java/lang/s_tan.lo java/lang/e_acos.lo java/lang/k_sin.lo \
java/util/TimeZone.lo java/util/Timer.lo \
java/util/TimerTask.lo java/util/TreeMap.lo \
java/util/TreeSet.lo java/util/TooManyListenersException.lo \
- java/util/Vector.lo java/util/WeakHashMap.lo \
- java/util/logging/ConsoleHandler.lo \
+ java/util/Vector.lo java/util/VMTimeZone.lo \
+ java/util/WeakHashMap.lo java/util/logging/ConsoleHandler.lo \
java/util/logging/ErrorManager.lo \
java/util/logging/FileHandler.lo java/util/logging/Filter.lo \
java/util/logging/Formatter.lo java/util/logging/Handler.lo \
java/util/TreeSet.java \
java/util/TooManyListenersException.java \
java/util/Vector.java \
+java/util/VMTimeZone.java \
java/util/WeakHashMap.java \
java/util/logging/ConsoleHandler.java \
java/util/logging/ErrorManager.java \
java/nio/natDirectByteBufferImpl.cc \
java/text/natCollator.cc \
java/util/natResourceBundle.cc \
-java/util/natTimeZone.cc \
+java/util/natVMTimeZone.cc \
java/util/zip/natDeflater.cc \
java/util/zip/natInflater.cc
@: > java/util/$(DEPDIR)/$(am__dirstamp)
java/util/natResourceBundle.lo: java/util/$(am__dirstamp) \
java/util/$(DEPDIR)/$(am__dirstamp)
-java/util/natTimeZone.lo: java/util/$(am__dirstamp) \
+java/util/natVMTimeZone.lo: java/util/$(am__dirstamp) \
java/util/$(DEPDIR)/$(am__dirstamp)
java/util/zip/$(am__dirstamp):
@$(mkdir_p) java/util/zip
java/util/$(DEPDIR)/$(am__dirstamp)
java/util/Vector.lo: java/util/$(am__dirstamp) \
java/util/$(DEPDIR)/$(am__dirstamp)
+java/util/VMTimeZone.lo: java/util/$(am__dirstamp) \
+ java/util/$(DEPDIR)/$(am__dirstamp)
java/util/WeakHashMap.lo: java/util/$(am__dirstamp) \
java/util/$(DEPDIR)/$(am__dirstamp)
java/util/logging/$(am__dirstamp):
-rm -f java/util/TreeMap.lo
-rm -f java/util/TreeSet.$(OBJEXT)
-rm -f java/util/TreeSet.lo
+ -rm -f java/util/VMTimeZone.$(OBJEXT)
+ -rm -f java/util/VMTimeZone.lo
-rm -f java/util/Vector.$(OBJEXT)
-rm -f java/util/Vector.lo
-rm -f java/util/WeakHashMap.$(OBJEXT)
-rm -f java/util/logging/XMLFormatter.lo
-rm -f java/util/natResourceBundle.$(OBJEXT)
-rm -f java/util/natResourceBundle.lo
- -rm -f java/util/natTimeZone.$(OBJEXT)
- -rm -f java/util/natTimeZone.lo
+ -rm -f java/util/natVMTimeZone.$(OBJEXT)
+ -rm -f java/util/natVMTimeZone.lo
-rm -f java/util/prefs/AbstractPreferences.$(OBJEXT)
-rm -f java/util/prefs/AbstractPreferences.lo
-rm -f java/util/prefs/BackingStoreException.$(OBJEXT)
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/TooManyListenersException.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/TreeMap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/TreeSet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/VMTimeZone.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/Vector.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/WeakHashMap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natResourceBundle.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natTimeZone.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@java/util/$(DEPDIR)/natVMTimeZone.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/jar/$(DEPDIR)/Attributes.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/jar/$(DEPDIR)/JarEntry.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@java/util/jar/$(DEPDIR)/JarException.Plo@am__quote@
class Comparable;
class Compiler;
class ConcreteProcess;
+ class ConcreteProcess$EOFInputStream;
class ConcreteProcess$ProcessManager;
class Double;
class Error;
class TreeMap$SubMap;
class TreeMap$TreeIterator;
class TreeSet;
+ class VMTimeZone;
class Vector;
class WeakHashMap;
class WeakHashMap$WeakBucket;
package java.util;
-import gnu.classpath.Configuration;
-import java.io.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.DateFormatSymbols;
/**
* Tries to get the default TimeZone for this system if not already
* set. It will call <code>getDefaultTimeZone(String)</code> with
- * the result of
- * <code>System.getProperty("user.timezone")</code>,
- * <code>System.getenv("TZ")</code>,
- * <code>readTimeZoneFile("/etc/timezone")</code>,
- * <code>readtzFile("/etc/localtime")</code> and
- * <code>getDefaultTimeZoneId()</code>
- * till a supported TimeZone is found.
- * If every method fails GMT is returned.
+ * the result of <code>System.getProperty("user.timezone")</code>.
+ * If that fails it calls <code>VMTimeZone.getDefaultTimeZoneId()</code>.
+ * If that also fails GMT is returned.
*/
private static synchronized TimeZone defaultZone()
{
{
public Object run()
{
- if (Configuration.INIT_LOAD_LIBRARY)
- {
- System.loadLibrary("javautil");
- }
-
TimeZone zone = null;
// Prefer System property user.timezone.
if (tzid != null && !tzid.equals(""))
zone = getDefaultTimeZone(tzid);
- // See if TZ environment variable is set and accessible.
- if (zone == null)
- {
- tzid = System.getenv("TZ");
- if (tzid != null && !tzid.equals(""))
- zone = getDefaultTimeZone(tzid);
- }
-
- // Try to parse /etc/timezone.
+ // Try platfom specific way.
if (zone == null)
- {
- tzid = readTimeZoneFile("/etc/timezone");
- if (tzid != null && !tzid.equals(""))
- zone = getDefaultTimeZone(tzid);
- }
-
- // Try to parse /etc/localtime
- if (zone == null)
- {
- tzid = readtzFile("/etc/localtime");
- if (tzid != null && !tzid.equals(""))
- zone = getDefaultTimeZone(tzid);
- }
-
- // Try some system specific way
- if (zone == null)
- {
- tzid = getDefaultTimeZoneId();
- if (tzid != null && !tzid.equals(""))
- zone = getDefaultTimeZone(tzid);
- }
+ zone = VMTimeZone.getDefaultTimeZoneId();
// Fall back on GMT.
if (zone == null)
return timezones0;
}
- /**
- * This method returns a time zone id string which is in the form
- * (standard zone name) or (standard zone name)(GMT offset) or
- * (standard zone name)(GMT offset)(daylight time zone name). The
- * GMT offset can be in seconds, or where it is evenly divisible by
- * 3600, then it can be in hours. The offset must be the time to
- * add to the local time to get GMT. If a offset is given and the
- * time zone observes daylight saving then the (daylight time zone
- * name) must also be given (otherwise it is assumed the time zone
- * does not observe any daylight savings).
- * <p>
- * The result of this method is given to getDefaultTimeZone(String)
- * which tries to map the time zone id to a known TimeZone. See
- * that method on how the returned String is mapped to a real
- * TimeZone object.
- */
- private static native String getDefaultTimeZoneId();
-
- /**
- * Tries to read the time zone name from a file. Only the first
- * consecutive letters, digits, slashes, dashes and underscores are
- * read from the file. If the file cannot be read or an IOException
- * occurs null is returned.
- * <p>
- * The /etc/timezone file is not standard, but a lot of systems have
- * it. If it exist the first line always contains a string
- * describing the timezone of the host of domain. Some systems
- * contain a /etc/TIMEZONE file which is used to set the TZ
- * environment variable (which is checked before /etc/timezone is
- * read).
- */
- private static String readTimeZoneFile(String file)
- {
- File f = new File(file);
- if (!f.exists())
- return null;
-
- InputStreamReader isr = null;
- try
- {
- FileInputStream fis = new FileInputStream(f);
- BufferedInputStream bis = new BufferedInputStream(fis);
- isr = new InputStreamReader(bis);
-
- StringBuffer sb = new StringBuffer();
- int i = isr.read();
- while (i != -1)
- {
- char c = (char) i;
- if (Character.isLetter(c) || Character.isDigit(c)
- || c == '/' || c == '-' || c == '_')
- {
- sb.append(c);
- i = isr.read();
- }
- else
- break;
- }
- return sb.toString();
- }
- catch (IOException ioe)
- {
- // Parse error, not a proper tzfile.
- return null;
- }
- finally
- {
- try
- {
- if (isr != null)
- isr.close();
- }
- catch (IOException ioe)
- {
- // Error while close, nothing we can do.
- }
- }
- }
-
- /**
- * Tries to read a file as a "standard" tzfile and return a time
- * zone id string as expected by <code>getDefaultTimeZone(String)</code>.
- * If the file doesn't exist, an IOException occurs or it isn't a tzfile
- * that can be parsed null is returned.
- * <p>
- * The tzfile structure (as also used by glibc) is described in the Olson
- * tz database archive as can be found at
- * <code>ftp://elsie.nci.nih.gov/pub/</code>.
- * <p>
- * At least the following platforms support the tzdata file format
- * and /etc/localtime (GNU/Linux, Darwin, Solaris and FreeBSD at
- * least). Some systems (like Darwin) don't start the file with the
- * required magic bytes 'TZif', this implementation can handle
- * that).
- */
- private static String readtzFile(String file)
- {
- File f = new File(file);
- if (!f.exists())
- return null;
-
- DataInputStream dis = null;
- try
- {
- FileInputStream fis = new FileInputStream(f);
- BufferedInputStream bis = new BufferedInputStream(fis);
- dis = new DataInputStream(bis);
-
- // Make sure we are reading a tzfile.
- byte[] tzif = new byte[4];
- dis.readFully(tzif);
- if (tzif[0] == 'T' && tzif[1] == 'Z'
- && tzif[2] == 'i' && tzif[3] == 'f')
- // Reserved bytes, ttisgmtcnt, ttisstdcnt and leapcnt
- skipFully(dis, 16 + 3 * 4);
- else
- // Darwin has tzdata files that don't start with the TZif marker
- skipFully(dis, 16 + 3 * 4 - 4);
-
- int timecnt = dis.readInt();
- int typecnt = dis.readInt();
- if (typecnt > 0)
- {
- int charcnt = dis.readInt();
- // Transition times plus indexed transition times.
- skipFully(dis, timecnt * (4 + 1));
-
- // Get last gmt_offset and dst/non-dst time zone names.
- int abbrind = -1;
- int dst_abbrind = -1;
- int gmt_offset = 0;
- while (typecnt-- > 0)
- {
- // gmtoff
- int offset = dis.readInt();
- int dst = dis.readByte();
- if (dst == 0)
- {
- abbrind = dis.readByte();
- gmt_offset = offset;
- }
- else
- dst_abbrind = dis.readByte();
- }
-
- // gmt_offset is the offset you must add to UTC/GMT to
- // get the local time, we need the offset to add to
- // the local time to get UTC/GMT.
- gmt_offset *= -1;
-
- // Turn into hours if possible.
- if (gmt_offset % 3600 == 0)
- gmt_offset /= 3600;
-
- if (abbrind >= 0)
- {
- byte[] names = new byte[charcnt];
- dis.readFully(names);
- int j = abbrind;
- while (j < charcnt && names[j] != 0)
- j++;
-
- String zonename = new String(names, abbrind, j - abbrind,
- "ASCII");
-
- String dst_zonename;
- if (dst_abbrind >= 0)
- {
- j = dst_abbrind;
- while (j < charcnt && names[j] != 0)
- j++;
- dst_zonename = new String(names, dst_abbrind,
- j - dst_abbrind, "ASCII");
- }
- else
- dst_zonename = "";
-
- // Only use gmt offset when necessary.
- // Also special case GMT+/- timezones.
- String offset_string;
- if ("".equals(dst_zonename)
- && (gmt_offset == 0
- || zonename.startsWith("GMT+")
- || zonename.startsWith("GMT-")))
- offset_string = "";
- else
- offset_string = Integer.toString(gmt_offset);
-
- String id = zonename + offset_string + dst_zonename;
-
- return id;
- }
- }
-
- // Something didn't match while reading the file.
- return null;
- }
- catch (IOException ioe)
- {
- // Parse error, not a proper tzfile.
- return null;
- }
- finally
- {
- try
- {
- if (dis != null)
- dis.close();
- }
- catch(IOException ioe)
- {
- // Error while close, nothing we can do.
- }
- }
- }
-
- /**
- * Skips the requested number of bytes in the given InputStream.
- * Throws EOFException if not enough bytes could be skipped.
- * Negative numbers of bytes to skip are ignored.
- */
- private static void skipFully(InputStream is, long l) throws IOException
- {
- while (l > 0)
- {
- long k = is.skip(l);
- if (k <= 0)
- throw new EOFException();
- l -= k;
- }
- }
-
/**
* Maps a time zone name (with optional GMT offset and daylight time
* zone name) to one of the known time zones. This method called
* The standard time zone name for The Netherlands is "Europe/Amsterdam",
* but can also be given as "CET-1CEST".
*/
- private static TimeZone getDefaultTimeZone(String sysTimeZoneId)
+ static TimeZone getDefaultTimeZone(String sysTimeZoneId)
{
// First find start of GMT offset info and any Daylight zone name.
int startGMToffset = 0;
for (int i = 0; i < sysTimeZoneIdLength && startGMToffset == 0; i++)
{
char c = sysTimeZoneId.charAt(i);
- if (c == '+' || c == '-' || Character.isDigit(c))
+ if (Character.isDigit(c))
+ startGMToffset = i;
+ else if ((c == '+' || c == '-')
+ && i + 1 < sysTimeZoneIdLength
+ && Character.isDigit(sysTimeZoneId.charAt(i + 1)))
startGMToffset = i;
}
// Offset could be in hours or seconds. Convert to millis.
// The offset is given as the time to add to local time to get GMT
// we need the time to add to GMT to get localtime.
- if (gmtOffset < 24)
+ if (Math.abs(gmtOffset) < 24)
gmtOffset *= 60 * 60;
gmtOffset *= -1000;
}
--- /dev/null
+/* java.util.VMTimeZone
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.Configuration;
+
+import java.io.*;
+
+/**
+ *
+ */
+final class VMTimeZone
+{
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("javautil");
+ }
+ }
+
+ /**
+ * This method returns a time zone id string which is in the form
+ * (standard zone name) or (standard zone name)(GMT offset) or
+ * (standard zone name)(GMT offset)(daylight time zone name). The
+ * GMT offset can be in seconds, or where it is evenly divisible by
+ * 3600, then it can be in hours. The offset must be the time to
+ * add to the local time to get GMT. If a offset is given and the
+ * time zone observes daylight saving then the (daylight time zone
+ * name) must also be given (otherwise it is assumed the time zone
+ * does not observe any daylight savings).
+ * <p>
+ * The result of this method is given to the method
+ * TimeZone.getDefaultTimeZone(String) which tries to map the time
+ * zone id to a known TimeZone. See that method on how the returned
+ * String is mapped to a real TimeZone object.
+ * <p>
+ * The reference implementation which is made for GNU/Posix like
+ * systems calls <code>System.getenv("TZ")</code>,
+ * <code>readTimeZoneFile("/etc/timezone")</code>,
+ * <code>readtzFile("/etc/localtime")</code> and finally
+ * <code>getSystemTimeZoneId()</code> till a supported TimeZone is
+ * found through <code>TimeZone.getDefaultTimeZone(String)</code>.
+ * If every method fails <code>null</code> is returned (which means
+ * the TimeZone code will fall back on GMT as default time zone).
+ * <p>
+ * Note that this method is called inside a
+ * <code>AccessController.doPrivileged()</code> block and runs with
+ * the priviliges of the java.util system classes. It will only be
+ * called when the default time zone is not yet set, the system
+ * property user.timezone isn't set and it is requested for the
+ * first time.
+ */
+ static TimeZone getDefaultTimeZoneId()
+ {
+ TimeZone zone = null;
+
+ // See if TZ environment variable is set and accessible.
+ String tzid = System.getenv("TZ");
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+
+ // Try to parse /etc/timezone.
+ if (zone == null)
+ {
+ tzid = readTimeZoneFile("/etc/timezone");
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+ }
+
+ // Try to parse /etc/localtime
+ if (zone == null)
+ {
+ tzid = readtzFile("/etc/localtime");
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+ }
+
+ // Try some system specific way
+ if (zone == null)
+ {
+ tzid = getSystemTimeZoneId();
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+ }
+
+ return zone;
+ }
+
+ /**
+ * Tries to read the time zone name from a file. Only the first
+ * consecutive letters, digits, slashes, dashes and underscores are
+ * read from the file. If the file cannot be read or an IOException
+ * occurs null is returned.
+ * <p>
+ * The /etc/timezone file is not standard, but a lot of systems have
+ * it. If it exist the first line always contains a string
+ * describing the timezone of the host of domain. Some systems
+ * contain a /etc/TIMEZONE file which is used to set the TZ
+ * environment variable (which is checked before /etc/timezone is
+ * read).
+ */
+ private static String readTimeZoneFile(String file)
+ {
+ File f = new File(file);
+ if (!f.exists())
+ return null;
+
+ InputStreamReader isr = null;
+ try
+ {
+ FileInputStream fis = new FileInputStream(f);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ isr = new InputStreamReader(bis);
+
+ StringBuffer sb = new StringBuffer();
+ int i = isr.read();
+ while (i != -1)
+ {
+ char c = (char) i;
+ if (Character.isLetter(c) || Character.isDigit(c)
+ || c == '/' || c == '-' || c == '_')
+ {
+ sb.append(c);
+ i = isr.read();
+ }
+ else
+ break;
+ }
+ return sb.toString();
+ }
+ catch (IOException ioe)
+ {
+ // Parse error, not a proper tzfile.
+ return null;
+ }
+ finally
+ {
+ try
+ {
+ if (isr != null)
+ isr.close();
+ }
+ catch (IOException ioe)
+ {
+ // Error while close, nothing we can do.
+ }
+ }
+ }
+
+ /**
+ * Tries to read a file as a "standard" tzfile and return a time
+ * zone id string as expected by <code>getDefaultTimeZone(String)</code>.
+ * If the file doesn't exist, an IOException occurs or it isn't a tzfile
+ * that can be parsed null is returned.
+ * <p>
+ * The tzfile structure (as also used by glibc) is described in the Olson
+ * tz database archive as can be found at
+ * <code>ftp://elsie.nci.nih.gov/pub/</code>.
+ * <p>
+ * At least the following platforms support the tzdata file format
+ * and /etc/localtime (GNU/Linux, Darwin, Solaris and FreeBSD at
+ * least). Some systems (like Darwin) don't start the file with the
+ * required magic bytes 'TZif', this implementation can handle
+ * that).
+ */
+ private static String readtzFile(String file)
+ {
+ File f = new File(file);
+ if (!f.exists())
+ return null;
+
+ DataInputStream dis = null;
+ try
+ {
+ FileInputStream fis = new FileInputStream(f);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ dis = new DataInputStream(bis);
+
+ // Make sure we are reading a tzfile.
+ byte[] tzif = new byte[4];
+ dis.readFully(tzif);
+ if (tzif[0] == 'T' && tzif[1] == 'Z'
+ && tzif[2] == 'i' && tzif[3] == 'f')
+ // Reserved bytes, ttisgmtcnt, ttisstdcnt and leapcnt
+ skipFully(dis, 16 + 3 * 4);
+ else
+ // Darwin has tzdata files that don't start with the TZif marker
+ skipFully(dis, 16 + 3 * 4 - 4);
+
+ int timecnt = dis.readInt();
+ int typecnt = dis.readInt();
+ if (typecnt > 0)
+ {
+ int charcnt = dis.readInt();
+ // Transition times plus indexed transition times.
+ skipFully(dis, timecnt * (4 + 1));
+
+ // Get last gmt_offset and dst/non-dst time zone names.
+ int abbrind = -1;
+ int dst_abbrind = -1;
+ int gmt_offset = 0;
+ while (typecnt-- > 0)
+ {
+ // gmtoff
+ int offset = dis.readInt();
+ int dst = dis.readByte();
+ if (dst == 0)
+ {
+ abbrind = dis.readByte();
+ gmt_offset = offset;
+ }
+ else
+ dst_abbrind = dis.readByte();
+ }
+
+ // gmt_offset is the offset you must add to UTC/GMT to
+ // get the local time, we need the offset to add to
+ // the local time to get UTC/GMT.
+ gmt_offset *= -1;
+
+ // Turn into hours if possible.
+ if (gmt_offset % 3600 == 0)
+ gmt_offset /= 3600;
+
+ if (abbrind >= 0)
+ {
+ byte[] names = new byte[charcnt];
+ dis.readFully(names);
+ int j = abbrind;
+ while (j < charcnt && names[j] != 0)
+ j++;
+
+ String zonename = new String(names, abbrind, j - abbrind,
+ "ASCII");
+
+ String dst_zonename;
+ if (dst_abbrind >= 0)
+ {
+ j = dst_abbrind;
+ while (j < charcnt && names[j] != 0)
+ j++;
+ dst_zonename = new String(names, dst_abbrind,
+ j - dst_abbrind, "ASCII");
+ }
+ else
+ dst_zonename = "";
+
+ // Only use gmt offset when necessary.
+ // Also special case GMT+/- timezones.
+ String offset_string;
+ if ("".equals(dst_zonename)
+ && (gmt_offset == 0
+ || zonename.startsWith("GMT+")
+ || zonename.startsWith("GMT-")))
+ offset_string = "";
+ else
+ offset_string = Integer.toString(gmt_offset);
+
+ String id = zonename + offset_string + dst_zonename;
+
+ return id;
+ }
+ }
+
+ // Something didn't match while reading the file.
+ return null;
+ }
+ catch (IOException ioe)
+ {
+ // Parse error, not a proper tzfile.
+ return null;
+ }
+ finally
+ {
+ try
+ {
+ if (dis != null)
+ dis.close();
+ }
+ catch(IOException ioe)
+ {
+ // Error while close, nothing we can do.
+ }
+ }
+ }
+
+ /**
+ * Skips the requested number of bytes in the given InputStream.
+ * Throws EOFException if not enough bytes could be skipped.
+ * Negative numbers of bytes to skip are ignored.
+ */
+ private static void skipFully(InputStream is, long l) throws IOException
+ {
+ while (l > 0)
+ {
+ long k = is.skip(l);
+ if (k <= 0)
+ throw new EOFException();
+ l -= k;
+ }
+ }
+
+ /**
+ * Tries to get the system time zone id through native code.
+ */
+ private static native String getSystemTimeZoneId();
+}
+++ /dev/null
-// natTimeZone.cc -- Native side of TimeZone class.
-
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation
-
- This file is part of libgcj.
-
-This software is copyrighted work licensed under the terms of the
-Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
-details. */
-
-#include <config.h>
-#include <platform.h>
-
-#include <gcj/cni.h>
-#include <jvm.h>
-
-#include <java/util/TimeZone.h>
-#include <java/lang/Character.h>
-#include <java/lang/Integer.h>
-
-#include <stdio.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-#include <string.h>
-
-/**
- * This method returns a time zone id string which is in the form
- * (standard zone name) or (standard zone name)(GMT offset) or
- * (standard zone name)(GMT offset)(daylight time zone name). The
- * GMT offset can be in seconds, or where it is evenly divisible by
- * 3600, then it can be in hours. The offset must be the time to
- * add to the local time to get GMT. If a offset is given and the
- * time zone observes daylight saving then the (daylight time zone
- * name) must also be given (otherwise it is assumed the time zone
- * does not observe any daylight savings).
- * <p>
- * The result of this method is given to getDefaultTimeZone(String)
- * which tries to map the time zone id to a known TimeZone. See
- * that method on how the returned String is mapped to a real
- * TimeZone object.
- */
-jstring
-java::util::TimeZone::getDefaultTimeZoneId ()
-{
- struct tm tim;
-#ifndef HAVE_LOCALTIME_R
- struct tm *lt_tim;
-#endif
-#ifdef HAVE_TM_ZONE
- int month;
-#endif
- time_t current_time;
- long tzoffset;
- const char *tz1, *tz2;
- char *tzid;
-
- time(¤t_time);
-#ifdef HAVE_LOCALTIME_R
- localtime_r(¤t_time, &tim);
-#else
- /* Fall back on non-thread safe localtime. */
- lt_tim = localtime(¤t_time);
- memcpy(&tim, lt_tim, sizeof (struct tm));
-#endif
- mktime(&tim);
-
-#ifdef HAVE_TM_ZONE
- /* We will cycle through the months to make sure we hit dst. */
- month = tim.tm_mon;
- tz1 = tz2 = NULL;
- while (tz1 == NULL || tz2 == NULL)
- {
- if (tim.tm_isdst > 0)
- tz2 = tim.tm_zone;
- else if (tz1 == NULL)
- {
- tz1 = tim.tm_zone;
- month = tim.tm_mon;
- }
-
- if (tz1 == NULL || tz2 == NULL)
- {
- tim.tm_mon++;
- tim.tm_mon %= 12;
- }
-
- if (tim.tm_mon == month && tz2 == NULL)
- tz2 = "";
- else
- mktime(&tim);
- }
- /* We want to make sure the tm struct we use later on is not dst. */
- tim.tm_mon = month;
- mktime(&tim);
-#elif defined (HAVE_TZNAME)
- /* If dst is never used, tzname[1] is the empty string. */
- tzset();
- tz1 = tzname[0];
- tz2 = tzname[1];
-#else
- /* Some targets have no concept of timezones. Assume GMT without dst. */
- tz1 = "GMT";
- tz2 = "";
-#endif
-
-#ifdef STRUCT_TM_HAS_GMTOFF
- /* tm_gmtoff is the number of seconds that you must add to GMT to get
- local time, we need the number of seconds to add to the local time
- to get GMT. */
- tzoffset = -1L * tim.tm_gmtoff;
-#elif HAVE_UNDERSCORE_TIMEZONE
- tzoffset = _timezone;
-#elif HAVE_TIMEZONE
- /* timezone is secs WEST of UTC. */
- tzoffset = timezone;
-#else
- /* FIXME: there must be another global if neither tm_gmtoff nor timezone
- is available, esp. if tzname is valid.
- Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to
- calculate between gmtime and localtime (and accounting for possible
- daylight savings time) as an alternative. */
- tzoffset = 0L;
-#endif
-
- if ((tzoffset % 3600) == 0)
- tzoffset = tzoffset / 3600;
-
- tzid = (char*) _Jv_Malloc (strlen(tz1) + strlen(tz2) + 6);
- sprintf(tzid, "%s%ld%s", tz1, tzoffset, tz2);
- jstring retval = JvNewStringUTF (tzid);
- _Jv_Free (tzid);
-
- return retval;
-}
--- /dev/null
+// natVMTimeZone.cc -- Native side of VMTimeZone class.
+
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+#include <platform.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/util/VMTimeZone.h>
+#include <java/lang/Character.h>
+#include <java/lang/Integer.h>
+
+#include <stdio.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include <string.h>
+
+/**
+ * This method returns a time zone id string which is in the form
+ * (standard zone name) or (standard zone name)(GMT offset) or
+ * (standard zone name)(GMT offset)(daylight time zone name). The
+ * GMT offset can be in seconds, or where it is evenly divisible by
+ * 3600, then it can be in hours. The offset must be the time to
+ * add to the local time to get GMT. If a offset is given and the
+ * time zone observes daylight saving then the (daylight time zone
+ * name) must also be given (otherwise it is assumed the time zone
+ * does not observe any daylight savings).
+ * <p>
+ * The result of this method is given to getDefaultTimeZone(String)
+ * which tries to map the time zone id to a known TimeZone. See
+ * that method on how the returned String is mapped to a real
+ * TimeZone object.
+ */
+jstring
+java::util::VMTimeZone::getSystemTimeZoneId()
+{
+ struct tm tim;
+#ifndef HAVE_LOCALTIME_R
+ struct tm *lt_tim;
+#endif
+#ifdef HAVE_TM_ZONE
+ int month;
+#endif
+ time_t current_time;
+ long tzoffset;
+ const char *tz1, *tz2;
+ char *tzid;
+
+ time(¤t_time);
+#ifdef HAVE_LOCALTIME_R
+ localtime_r(¤t_time, &tim);
+#else
+ /* Fall back on non-thread safe localtime. */
+ lt_tim = localtime(¤t_time);
+ memcpy(&tim, lt_tim, sizeof (struct tm));
+#endif
+ mktime(&tim);
+
+#ifdef HAVE_TM_ZONE
+ /* We will cycle through the months to make sure we hit dst. */
+ month = tim.tm_mon;
+ tz1 = tz2 = NULL;
+ while (tz1 == NULL || tz2 == NULL)
+ {
+ if (tim.tm_isdst > 0)
+ tz2 = tim.tm_zone;
+ else if (tz1 == NULL)
+ {
+ tz1 = tim.tm_zone;
+ month = tim.tm_mon;
+ }
+
+ if (tz1 == NULL || tz2 == NULL)
+ {
+ tim.tm_mon++;
+ tim.tm_mon %= 12;
+ }
+
+ if (tim.tm_mon == month && tz2 == NULL)
+ tz2 = "";
+ else
+ mktime(&tim);
+ }
+ /* We want to make sure the tm struct we use later on is not dst. */
+ tim.tm_mon = month;
+ mktime(&tim);
+#elif defined (HAVE_TZNAME)
+ /* If dst is never used, tzname[1] is the empty string. */
+ tzset();
+ tz1 = tzname[0];
+ tz2 = tzname[1];
+#else
+ /* Some targets have no concept of timezones. Assume GMT without dst. */
+ tz1 = "GMT";
+ tz2 = "";
+#endif
+
+#ifdef STRUCT_TM_HAS_GMTOFF
+ /* tm_gmtoff is the number of seconds that you must add to GMT to get
+ local time, we need the number of seconds to add to the local time
+ to get GMT. */
+ tzoffset = -1L * tim.tm_gmtoff;
+#elif HAVE_UNDERSCORE_TIMEZONE
+ tzoffset = _timezone;
+#elif HAVE_TIMEZONE
+ /* timezone is secs WEST of UTC. */
+ tzoffset = timezone;
+#else
+ /* FIXME: there must be another global if neither tm_gmtoff nor timezone
+ is available, esp. if tzname is valid.
+ Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to
+ calculate between gmtime and localtime (and accounting for possible
+ daylight savings time) as an alternative. */
+ tzoffset = 0L;
+#endif
+
+ if ((tzoffset % 3600) == 0)
+ tzoffset = tzoffset / 3600;
+
+ tzid = (char*) _Jv_Malloc (strlen(tz1) + strlen(tz2) + 6);
+ sprintf(tzid, "%s%ld%s", tz1, tzoffset, tz2);
+ jstring retval = JvNewStringUTF (tzid);
+ _Jv_Free (tzid);
+
+ return retval;
+}