/[classpath]/classpath/java/util/TimeZone.java
ViewVC logotype

Diff of /classpath/java/util/TimeZone.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.31 by smarothy, Fri Feb 18 17:00:27 2005 UTC revision 1.32 by smarothy, Wed Jun 1 04:07:36 2005 UTC
# Line 1  Line 1 
1  /* java.util.TimeZone  /* java.util.TimeZone
2     Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004     Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3     Free Software Foundation, Inc.     Free Software Foundation, Inc.
4    
5  This file is part of GNU Classpath.  This file is part of GNU Classpath.
# Line 810  public abstract class TimeZone implement Line 810  public abstract class TimeZone implement
810     * with the result of <code>System.getProperty("user.timezone")</code>     * with the result of <code>System.getProperty("user.timezone")</code>
811     * or <code>getDefaultTimeZoneId()</code>.  Note that giving one of     * or <code>getDefaultTimeZoneId()</code>.  Note that giving one of
812     * the standard tz data names from ftp://elsie.nci.nih.gov/pub/ is     * the standard tz data names from ftp://elsie.nci.nih.gov/pub/ is
813     * preferred.  The time zone name can be given as follows:     * preferred.  
814     * <code>(standard zone name)[(GMT offset)[(daylight time zone name)]]</code>     * The time zone name can be given as follows:
815       * <code>(standard zone name)[(GMT offset)[(DST zone name)[DST offset]]]
816       * </code>
817     * <p>     * <p>
818     * If only a (standard zone name) is given (no numbers in the     * If only a (standard zone name) is given (no numbers in the
819     * String) then it gets mapped directly to the TimeZone with that     * String) then it gets mapped directly to the TimeZone with that
820     * name, if that fails null is returned.     * name, if that fails null is returned.
821     * <p>     * <p>
822       * Alternately, a POSIX-style TZ string can be given, defining the time zone:
823       * <code>std offset dst offset,date/time,date/time</code>
824       * See the glibc manual, or the man page for <code>tzset</code> for details
825       * of this format.
826       * <p>
827     * A GMT offset is the offset to add to the local time to get GMT.     * A GMT offset is the offset to add to the local time to get GMT.
828     * If a (GMT offset) is included (either in seconds or hours) then     * If a (GMT offset) is included (either in seconds or hours) then
829     * an attempt is made to find a TimeZone name matching both the name     * an attempt is made to find a TimeZone name matching both the name
# Line 843  public abstract class TimeZone implement Line 850  public abstract class TimeZone implement
850     */     */
851    static TimeZone getDefaultTimeZone(String sysTimeZoneId)    static TimeZone getDefaultTimeZone(String sysTimeZoneId)
852    {    {
853      // First find start of GMT offset info and any Daylight zone name.      String stdName = null;
854      int startGMToffset = 0;      String dstName;
855      int sysTimeZoneIdLength = sysTimeZoneId.length();      int stdOffs;
856      for (int i = 0; i < sysTimeZoneIdLength && startGMToffset == 0; i++)      int dstOffs;
857        try
858        {        {
859          char c = sysTimeZoneId.charAt(i);          int idLength = sysTimeZoneId.length();
860          if (Character.isDigit(c))  
861            startGMToffset = i;          int index = 0;
862          else if ((c == '+' || c == '-')          int prevIndex;
863                   && i + 1 < sysTimeZoneIdLength          char c;
864                   && Character.isDigit(sysTimeZoneId.charAt(i + 1)))  
865            startGMToffset = i;          // get std
866            do
867              c = sysTimeZoneId.charAt(index++);
868            while (c != '+' && c != '-' && c != ',' && c != ':'
869                   && ! Character.isDigit(c) && c != '\0' && index < idLength);
870    
871            if (index >= idLength)
872              return (TimeZone)timezones().get(sysTimeZoneId);
873    
874            stdName = sysTimeZoneId.substring(0, --index);
875            prevIndex = index;
876    
877            // get the std offset
878            do
879              c = sysTimeZoneId.charAt(index++);
880            while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
881                   && index < idLength);
882            if (index < idLength)
883              index--;
884    
885            { // convert the dst string to a millis number
886                String offset = sysTimeZoneId.substring(prevIndex, index);
887                prevIndex = index;
888    
889                if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
890                  stdOffs = parseTime(offset.substring(1));
891                else
892                  stdOffs = parseTime(offset);
893    
894                if (offset.charAt(0) == '-')
895                  stdOffs = -stdOffs;
896    
897                // TZ timezone offsets are positive when WEST of the meridian.
898                stdOffs = -stdOffs;
899            }
900    
901            // Done yet? (Format: std offset)
902            if (index >= idLength)
903              {
904                // Do we have an existing timezone with that name and offset?
905                TimeZone tz = (TimeZone) timezones().get(stdName);
906                if (tz != null)
907                  if (tz.getRawOffset() == stdOffs)
908                    return tz;
909    
910                // Custom then.
911                return new SimpleTimeZone(stdOffs, stdName);
912              }
913    
914            // get dst
915            do
916              c = sysTimeZoneId.charAt(index++);
917            while (c != '+' && c != '-' && c != ',' && c != ':'
918                   && ! Character.isDigit(c) && c != '\0' && index < idLength);
919    
920            // Done yet? (Format: std offset dst)
921            if (index >= idLength)
922              {
923                // Do we have an existing timezone with that name and offset
924                // which has DST?
925                TimeZone tz = (TimeZone) timezones().get(stdName);
926                if (tz != null)
927                  if (tz.getRawOffset() == stdOffs && tz.useDaylightTime())
928                    return tz;
929    
930                // Custom then.
931                return new SimpleTimeZone(stdOffs, stdName);
932              }
933    
934            // get the dst offset
935            dstName = sysTimeZoneId.substring(prevIndex, --index);
936            prevIndex = index;
937            do
938              c = sysTimeZoneId.charAt(index++);
939            while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
940                   && index < idLength);
941            if (index < idLength)
942              index--;
943    
944            { // convert the dst string to a millis number
945                String offset = sysTimeZoneId.substring(prevIndex, index);
946                prevIndex = index;
947    
948                if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
949                  dstOffs = parseTime(offset.substring(1));
950                else
951                  dstOffs = parseTime(offset);
952    
953                if (offset.charAt(0) == '-')
954                  dstOffs = -dstOffs;
955    
956                // TZ timezone offsets are positive when WEST of the meridian.
957                dstOffs = -dstOffs;
958            }
959    
960            // Done yet? (Format: std offset dst offset)
961            // FIXME: We don't support DST without a rule given. Should we?
962            if (index >= idLength)
963              {
964                // Time Zone existing with same name, dst and offsets?
965                TimeZone tz = (TimeZone) timezones().get(stdName);
966                if (tz != null)
967                  if (tz.getRawOffset() == stdOffs && tz.useDaylightTime()
968                      && tz.getDSTSavings() == (dstOffs - stdOffs))
969                    return tz;
970    
971                return new SimpleTimeZone(stdOffs, stdName);
972              }
973    
974            // get the DST rule
975            if (sysTimeZoneId.charAt(index) == ','
976                || sysTimeZoneId.charAt(index) == ';')
977              {
978                index++;
979                int offs = index;
980                while (sysTimeZoneId.charAt(index) != ','
981                       && sysTimeZoneId.charAt(index) != ';')
982                  index++;
983                String startTime = sysTimeZoneId.substring(offs, index);
984                index++;
985                String endTime = sysTimeZoneId.substring(index);
986    
987                index = startTime.indexOf('/');
988                int startMillis;
989                int endMillis;
990                String startDate;
991                String endDate;
992                if (index != -1)
993                  {
994                    startDate = startTime.substring(0, index);
995                    startMillis = parseTime(startTime.substring(index + 1));
996                  }
997                else
998                  {
999                    startDate = startTime;
1000                    // if time isn't given, default to 2:00:00 AM.
1001                    startMillis = 2 * 60 * 60 * 1000;
1002                  }
1003                index = endTime.indexOf('/');
1004                if (index != -1)
1005                  {
1006                    endDate = endTime.substring(0, index);
1007                    endMillis = parseTime(endTime.substring(index + 1));
1008                  }
1009                else
1010                  {
1011                    endDate = endTime;
1012                    // if time isn't given, default to 2:00:00 AM.
1013                    endMillis = 2 * 60 * 60 * 1000;
1014                  }
1015    
1016                int[] start = getDateParams(startDate);
1017                int[] end = getDateParams(endDate);
1018                return new SimpleTimeZone(stdOffs, stdName, start[0], start[1],
1019                                          start[2], startMillis, end[0], end[1],
1020                                          end[2], endMillis, (dstOffs - stdOffs));
1021              }
1022        }        }
1023        
1024      String tzBasename;      // FIXME: Produce a warning here?
1025      if (startGMToffset == 0)      catch (IndexOutOfBoundsException _)
       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)  
1026        {        {
         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 (Math.abs(gmtOffset) < 24)  
           gmtOffset *= 60 * 60;  
         gmtOffset *= -1000;  
1027        }        }
1028            catch (NumberFormatException _)
     // 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)  
1029        {        {
         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;  
           }  
1030        }        }
1031        
1032      // If no match, see if a valid timezone has similar attributes as this      return null;
1033      // and then use it instead. We take the first one that looks OKish.    }
1034      if (startGMToffset > 0)  
1035      /**
1036       * Parses and returns the params for a POSIX TZ date field,
1037       * in the format int[]{ month, day, dayOfWeek }, following the
1038       * SimpleTimeZone constructor rules.
1039       */
1040      private static int[] getDateParams(String date)
1041      {
1042        int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1043        int month;
1044    
1045        if (date.charAt(0) == 'M' || date.charAt(0) == 'm')
1046        {        {
1047          String[] ids = getAvailableIDs(gmtOffset);          int day;
1048          for (int i = 0; i < ids.length; i++)  
1049            {          // Month, week of month, day of week
1050              tz = (TimeZone) timezones().get(ids[i]);          month = Integer.parseInt(date.substring(1, date.indexOf('.')));
1051              if (tz.useDaylightTime() == useDaylightTime)          int week = Integer.parseInt(date.substring(date.indexOf('.') + 1,
1052                return tz;                                                     date.lastIndexOf('.')));
1053            }          int dayOfWeek = Integer.parseInt(date.substring(date.lastIndexOf('.')
1054                                                            + 1));
1055            if (week == 5)
1056              day = -1; // last day of month is -1 in java, 5 in TZ
1057            else
1058              // first day of week starting on or after.
1059              day = (week - 1) * 7 + 1;
1060    
1061            dayOfWeek++; // Java day of week is one-based, Sunday is first day.
1062            month--; // Java month is zero-based.
1063            return new int[] { month, day, dayOfWeek };
1064        }        }
1065        
1066      return null;      // julian day, either zero-based 0<=n<=365 (incl feb 29)
1067        // or one-based 1<=n<=365 (no feb 29)
1068        int julianDay; // Julian day,
1069    
1070        if (date.charAt(0) != 'J' || date.charAt(0) != 'j')
1071          {
1072            julianDay = Integer.parseInt(date.substring(1));
1073            julianDay++; // make 1-based
1074            // Adjust day count to include feb 29.
1075            dayCount = new int[]
1076                       {
1077                         0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
1078                       };
1079          }
1080        else
1081          // 1-based julian day
1082          julianDay = Integer.parseInt(date);
1083    
1084        int i = 11;
1085        while (i > 0)
1086          if (dayCount[i] < julianDay)
1087            break;
1088          else
1089            i--;
1090        julianDay -= dayCount[i];
1091        month = i;
1092        return new int[] { month, julianDay, 0 };
1093      }
1094    
1095      /**
1096       * Parses a time field hh[:mm[:ss]], returning the result
1097       * in milliseconds. No leading sign.
1098       */
1099      private static int parseTime(String time)
1100      {
1101        int millis = 0;
1102        int i = 0;
1103    
1104        while (i < time.length())
1105          if (time.charAt(i) == ':')
1106            break;
1107          else
1108            i++;
1109        millis = 60 * 60 * 1000 * Integer.parseInt(time.substring(0, i));
1110        if (i >= time.length())
1111          return millis;
1112    
1113        int iprev = ++i;
1114        while (i < time.length())
1115          if (time.charAt(i) == ':')
1116            break;
1117          else
1118            i++;
1119        if (i >= time.length())
1120          return millis;
1121    
1122        millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i));
1123        millis += 1000 * Integer.parseInt(time.substring(++i));
1124        return millis;
1125    }    }
1126    
1127    /**    /**

Legend:
Removed from v.1.31  
changed lines
  Added in v.1.32

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26