re PR libgcj/17002 (java.util.TimeZone.getDefault() is broken)
authorMark Wielaard <mark@klomp.org>
Thu, 26 Aug 2004 16:10:54 +0000 (16:10 +0000)
committerMark Wielaard <mark@gcc.gnu.org>
Thu, 26 Aug 2004 16:10:54 +0000 (16:10 +0000)
2004-08-26  Mark Wielaard  <mark@klomp.org>

       Fixes PR libgcj/17002:
       * java/util/TimeZone.java (defaultZone): Try a couple of ways to get
       a TimeZoneId string and then try to convert that to a TimeZone with
       getDefaultSystemTimeZone(String).
       (timezones0): Changed type from Hashtable to HashMap.
       (timezones): Create HashMap, not Hashtable.
       (getDefaultTimeZone): New method, rewritten from CNI version.
       (readTimeZoneFile): New method.
       (readtzFile): Likewise.
       (skipFully): Likewise.
       * java/util/natTimeZone.cc (getSystemTimeZone): Renamed to
       getDefaultTimeZoneId and rewritten.
       (getDefaultTimeZoneId): Rewritten in java.

From-SVN: r86623

libjava/ChangeLog
libjava/java/util/TimeZone.java
libjava/java/util/natTimeZone.cc

index 853d41d4ab34b8cb2a6384116a999534f5c024b9..fb6d55596b34da9d6c2416c85e13f797644f5868 100644 (file)
@@ -1,3 +1,19 @@
+2004-08-26  Mark Wielaard  <mark@klomp.org>
+
+       Fixes PR libgcj/17002:
+       * java/util/TimeZone.java (defaultZone): Try a couple of ways to get
+       a TimeZoneId string and then try to convert that to a TimeZone with
+       getDefaultSystemTimeZone(String).
+       (timezones0): Changed type from Hashtable to HashMap.
+       (timezones): Create HashMap, not Hashtable.
+       (getDefaultTimeZone): New method, rewritten from CNI version.
+       (readTimeZoneFile): New method.
+       (readtzFile): Likewise.
+       (skipFully): Likewise.
+       * java/util/natTimeZone.cc (getSystemTimeZone): Renamed to
+       getDefaultTimeZoneId and rewritten.
+       (getDefaultTimeZoneId): Rewritten in java.
+       
 2004-08-25  David Daney  <daney@avtrex.com>
 
        * Makefile.am (AM_GCJFLAGS):  Add LIBGCJ_JAVAFLAGS.
index 504d34e7ffa910784f365dcf3519dbfb4de50188..cc3c7a3d283314c782aef3f08ea23b1bba834a23 100644 (file)
@@ -40,6 +40,9 @@ exception statement from your version. */
 package java.util;
 import gnu.classpath.Configuration;
 
+import java.io.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.text.DateFormatSymbols;
 
 /**
@@ -83,44 +86,99 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
    * The default time zone, as returned by getDefault.
    */
   private static TimeZone defaultZone0;
-  /* initialize this static field lazily to overhead if
-   * it is not needed: 
+
+  /**
+   * 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.
    */
-  private static synchronized TimeZone defaultZone() {
+  private static synchronized TimeZone defaultZone()
+  {
     /* Look up default timezone */
     if (defaultZone0 == null) 
       {
-       if (Configuration.INIT_LOAD_LIBRARY)
-         {
-           System.loadLibrary("javautil");
-         }
-       String tzid = System.getProperty("user.timezone");
-       
-       if (tzid == null)
-         tzid = getDefaultTimeZoneId();
-       
-       if (tzid == null)
-         tzid = "GMT";
-       
-       defaultZone0 = getTimeZone(tzid);
+       defaultZone0 = (TimeZone) AccessController.doPrivileged
+         (new PrivilegedAction()
+           {
+             public Object run()
+             {
+               if (Configuration.INIT_LOAD_LIBRARY)
+                 {
+                   System.loadLibrary("javautil");
+                 }
+               
+               TimeZone zone = null;
+               
+               // Prefer System property user.timezone.
+               String tzid = System.getProperty("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.
+               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);
+                 }
+               
+               // Fall back on GMT.
+               if (zone == null)
+                 zone = (TimeZone) timezones().get("GMT");
+               
+               return zone;
+             }
+           });
       }
+    
     return defaultZone0; 
   }
-
-
+  
   private static final long serialVersionUID = 3581463369166924961L;
 
   /**
-   * Hashtable for timezones by ID.  
+   * HashMap for timezones by ID.  
    */
-  private static Hashtable timezones0;
+  private static HashMap timezones0;
   /* initialize this static field lazily to overhead if
    * it is not needed: 
    */
-  private static synchronized Hashtable timezones() {
-    if (timezones0==null) 
+  private static synchronized HashMap timezones()
+  {
+    if (timezones0 == null) 
       {
-       Hashtable timezones = new Hashtable();
+       HashMap timezones = new HashMap();
        timezones0 = timezones;
 
        TimeZone tz;
@@ -784,18 +842,362 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
     return timezones0;
   }
 
-
-  /* This method returns us a time zone id string which is in the
-     form <standard zone name><GMT offset><daylight time zone name>.
-     The GMT offset is in seconds, except where it is evenly divisible
-     by 3600, then it is in hours.  If the zone does not observe
-     daylight time, then the daylight zone name is omitted.  Examples:
-     in Chicago, the timezone would be CST6CDT.  In Indianapolis 
-     (which does not have Daylight Savings Time) the string would
-     be EST5
+  /**
+   * 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
+   * with the result of <code>System.getProperty("user.timezone")</code>
+   * or <code>getDefaultTimeZoneId()</code>.  Note that giving one of
+   * the standard tz data names from ftp://elsie.nci.nih.gov/pub/ is
+   * preferred.  The time zone name can be given as follows:
+   * <code>(standard zone name)[(GMT offset)[(daylight time zone name)]]</code>
+   * <p>
+   * If only a (standard zone name) is given (no numbers in the
+   * String) then it gets mapped directly to the TimeZone with that
+   * name, if that fails null is returned.
+   * <p>
+   * A GMT offset is the offset to add to the local time to get GMT.
+   * If a (GMT offset) is included (either in seconds or hours) then
+   * an attempt is made to find a TimeZone name matching both the name
+   * and the offset (that doesn't observe daylight time, if the
+   * timezone observes daylight time then you must include a daylight
+   * time zone name after the offset), if that fails then a TimeZone
+   * with the given GMT offset is returned (whether or not the
+   * TimeZone observes daylight time is ignored), if that also fails
+   * the GMT TimeZone is returned.
+   * <p>
+   * If the String ends with (GMT offset)(daylight time zone name)
+   * then an attempt is made to find a TimeZone with the given name and
+   * GMT offset that also observes (the daylight time zone name is not
+   * currently used in any other way), if that fails a TimeZone with
+   * the given GMT offset that observes daylight time is returned, if
+   * that also fails the GMT TimeZone is returned.
+   * <p>
+   * Examples: In Chicago, the time zone id could be "CST6CDT", but
+   * the preferred name would be "America/Chicago".  In Indianapolis
+   * (which does not have Daylight Savings Time) the string could be
+   * "EST5", but the preferred name would be "America/Indianapolis".
+   * 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)
+  {
+    // First find start of GMT offset info and any Daylight zone name.
+    int startGMToffset = 0;
+    int sysTimeZoneIdLength = sysTimeZoneId.length();
+    for (int i = 0; i < sysTimeZoneIdLength && startGMToffset == 0; i++)
+      {
+       char c = sysTimeZoneId.charAt(i);
+       if (c == '+' || c == '-' || Character.isDigit(c))
+         startGMToffset = i;
+      }
+    
+    String tzBasename;
+    if (startGMToffset == 0)
+      tzBasename = sysTimeZoneId;
+    else
+      tzBasename = sysTimeZoneId.substring (0, startGMToffset);
+    
+    int startDaylightZoneName = 0;
+    for (int i = sysTimeZoneIdLength - 1;
+        i >= 0 && !Character.isDigit(sysTimeZoneId.charAt(i)); --i)
+      startDaylightZoneName = i;
+    
+    boolean useDaylightTime = startDaylightZoneName > 0;
+    
+    // Integer.parseInt() doesn't handle leading +.
+    if (sysTimeZoneId.charAt(startGMToffset) == '+')
+      startGMToffset++;
+    
+    int gmtOffset = 0;
+    if (startGMToffset > 0)
+      {
+       gmtOffset = Integer.parseInt
+         (startDaylightZoneName == 0
+          ? sysTimeZoneId.substring(startGMToffset)
+          : sysTimeZoneId.substring(startGMToffset,
+                                    startDaylightZoneName));
+       
+       // 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)
+         gmtOffset *= 60 * 60;
+       gmtOffset *= -1000;
+      }
+    
+    // Try to be optimistic and get the timezone that matches the base name.
+    // If we only have the base name then just accept this timezone.
+    // Otherwise check the gmtOffset and day light attributes.
+    TimeZone tz = (TimeZone) timezones().get(tzBasename);
+    if (tz != null
+       && (tzBasename == sysTimeZoneId
+           || (tz.getRawOffset() == gmtOffset
+               && tz.useDaylightTime() == useDaylightTime)))
+      return tz;
+    
+    // Maybe there is one with the daylight zone name?
+    if (useDaylightTime)
+      {
+       String daylightZoneName;
+       daylightZoneName = sysTimeZoneId.substring(startDaylightZoneName);
+       if (!daylightZoneName.equals(tzBasename))
+         {
+           tz = (TimeZone) timezones().get(tzBasename);
+           if (tz != null
+               && tz.getRawOffset() == gmtOffset
+               && tz.useDaylightTime())
+             return tz;
+         }
+      }
+    
+    // If no match, see if a valid timezone has similar attributes as this
+    // and then use it instead. We take the first one that looks OKish.
+    if (startGMToffset > 0)
+      {
+       String[] ids = getAvailableIDs(gmtOffset);
+       for (int i = 0; i < ids.length; i++)
+         {
+           tz = (TimeZone) timezones().get(ids[i]);
+           if (tz.useDaylightTime() == useDaylightTime)
+             return tz;
+         }
+      }
+    
+    return null;
+  }
+
   /**
    * Gets the time zone offset, for current date, modified in case of 
    * daylight savings.  This is the offset to add to UTC to get the local
@@ -1140,16 +1542,18 @@ public abstract class TimeZone implements java.io.Serializable, Cloneable
   /**
    * Returns the time zone under which the host is running.  This
    * can be changed with setDefault.
-   * @return the time zone for this host.
+   *
+   * @return A clone of the current default time zone for this host.
    * @see #setDefault
    */
   public static TimeZone getDefault()
   {
-    return defaultZone();
+    return (TimeZone) defaultZone().clone();
   }
 
   public static void setDefault(TimeZone zone)
   {
+    // Hmmmm. No Security checks?
     defaultZone0 = zone;
   }
 
index cb564a9759118edc4a68221e94d785e41c6d667c..c23d9e6555e5fa8ca602b225591187a7167c229e 100644 (file)
@@ -1,6 +1,7 @@
 // natTimeZone.cc -- Native side of TimeZone class.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation
 
    This file is part of libgcj.
 
@@ -33,53 +34,105 @@ details.  */
 
 #include <string.h>
 
-/*
- * This method returns a time zone string that is used by init_properties
- * to set the default timezone property 'user.timezone'.  That value is
- * used by default as a key into the timezone table used by the
- * java::util::TimeZone class.
+/**
+ * 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.
  */
-static jstring
-getSystemTimeZone (void)
+jstring
+java::util::TimeZone::getDefaultTimeZoneId ()
 {
-  struct tm *tim;
+  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;
 
-  current_time = time(0);
+  time(&current_time);
+#ifdef HAVE_LOCALTIME_R
+  localtime_r(&current_time, &tim);
+#else
+  /* Fall back on non-thread safe localtime. */
+  lt_tim = localtime(&current_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
 
-  mktime(tim = localtime(&current_time));
 #ifdef STRUCT_TM_HAS_GMTOFF
-  // tm_gmtoff is secs EAST of UTC.
-  tzoffset = -(tim->tm_gmtoff) + tim->tm_isdst * 3600L;
+  /* 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.
+  /* 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.
+  /* 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
 
-#ifdef HAVE_TM_ZONE
-  tz1 = tim->tm_zone;
-  tz2 = "";
-#elif defined (HAVE_TZNAME)
-  tz1 = tzname[0];
-  tz2 = strcmp (tzname[0], tzname[1]) ? tzname[1] : "";
-#else
-  // Some targets have no concept of timezones.
-  tz1 = "???";
-  tz2 = tz1;
-#endif
-
   if ((tzoffset % 3600) == 0)
     tzoffset = tzoffset / 3600;
 
@@ -90,81 +143,3 @@ getSystemTimeZone (void)
 
   return retval;
 }
-
-// Get the System Timezone as reported by the OS.  It should be in
-// the form PST8PDT so we'll need to parse it and check that it's valid.
-// FIXME: Using the code from Classpath for generating the System
-// Timezone IMO is suboptimal because it ignores whether the rules for
-// DST match up.
-jstring
-java::util::TimeZone::getDefaultTimeZoneId ()
-{
-  jstring sysTimeZoneId = getSystemTimeZone ();
-
-  using namespace java::lang;
-
-  // Check if this is a valid timezone.  Make sure the IDs match
-  // since getTimeZone returns GMT if no match is found.
-  TimeZone *tz = TimeZone::getTimeZone (sysTimeZoneId);
-  if (tz->getID ()->equals (sysTimeZoneId))
-    return sysTimeZoneId;
-
-  // Check if the base part of sysTimeZoneId is a valid timezone that
-  // matches with daylight usage and rawOffset.  Make sure the IDs match
-  // since getTimeZone returns GMT if no match is found.
-  // First find start of GMT offset info and any Daylight zone name.
-  int startGMToffset = 0;
-  int sysTimeZoneIdLength = sysTimeZoneId->length();
-  for (int i = 0; i < sysTimeZoneIdLength && startGMToffset == 0; i++)
-    {
-      if (Character::isDigit (sysTimeZoneId->charAt (i)))
-       startGMToffset = i;
-    }
-
-  int startDaylightZoneName = 0;
-  jboolean usesDaylight = false;
-  for (int i = sysTimeZoneIdLength - 1;
-       i >= 0 && !Character::isDigit (sysTimeZoneId->charAt (i)); --i)
-    {
-      startDaylightZoneName = i;
-    }
-  if (startDaylightZoneName > 0)
-    usesDaylight = true;
-
-  int GMToffset
-    = Integer::parseInt (startDaylightZoneName == 0 ?
-                        sysTimeZoneId->substring (startGMToffset) :
-                        sysTimeZoneId->substring (startGMToffset,
-                                                  startDaylightZoneName));
-
-  // Offset could be in hours or seconds.  Convert to millis.
-  if (GMToffset < 24)
-    GMToffset *= 60 * 60;
-  GMToffset *= -1000;
-
-  jstring tzBasename = sysTimeZoneId->substring (0, startGMToffset);
-  tz = TimeZone::getTimeZone (tzBasename);
-  if (tz->getID ()->equals (tzBasename) && tz->getRawOffset () == GMToffset)
-    {
-      jboolean tzUsesDaylight = tz->useDaylightTime ();
-      if (usesDaylight && tzUsesDaylight || !usesDaylight && !tzUsesDaylight)
-       return tzBasename;
-    }
-
-  // If no match, see if a valid timezone has the same attributes as this
-  // and then use it instead.
-  jstringArray IDs = TimeZone::getAvailableIDs (GMToffset);
-  jstring *elts = elements (IDs);
-  for (int i = 0; i < IDs->length; ++i)
-    {
-      // FIXME: The daylight savings rules may not match the rules
-      // for the desired zone.
-      jboolean IDusesDaylight =
-       TimeZone::getTimeZone (elts[i])->useDaylightTime ();
-      if (usesDaylight && IDusesDaylight || !usesDaylight && !IDusesDaylight)
-       return elts[i];
-    }
-
-  // If all else fails, return null.
-  return NULL;
-}