home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / util / Date.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  46.4 KB  |  1,125 lines

  1. /*
  2.  * @(#)Date.java    1.52 98/03/18
  3.  *
  4.  * Copyright 1994-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.util;
  16.  
  17. import java.util.Calendar;
  18. import java.util.GregorianCalendar;
  19. import java.util.TimeZone;
  20. import java.text.DateFormat;
  21. import java.text.SimpleDateFormat;
  22. import java.io.IOException;
  23. import java.io.ObjectOutputStream;
  24. import java.io.ObjectInputStream;
  25. import java.lang.ref.SoftReference;
  26.  
  27. /**
  28.  * The class <code>Date</code> represents a specific instant
  29.  * in time, with millisecond precision.
  30.  * <p>
  31.  * Prior to JDK 1.1, the class <code>Date</code> had two additional
  32.  * functions.  It allowed the interpretation of dates as year, month, day, hour,
  33.  * minute, and second values.  It also allowed the formatting and parsing
  34.  * of date strings.  Unfortunately, the API for these functions was not
  35.  * amenable to internationalization.  As of JDK 1.1, the
  36.  * <code>Calendar</code> class should be used to convert between dates and time
  37.  * fields and the <code>DateFormat</code> class should be used to format and
  38.  * parse date strings.
  39.  * The corresponding methods in <code>Date</code> are deprecated.
  40.  * <p>
  41.  * Although the <code>Date</code> class is intended to reflect 
  42.  * coordinated universal time (UTC), it may not do so exactly, 
  43.  * depending on the host environment of the Java Virtual Machine. 
  44.  * Nearly all modern operating systems assume that 1 day =
  45.  * 24 × 60 × 60 = 86400 seconds 
  46.  * in all cases. In UTC, however, about once every year or two there 
  47.  * is an extra second, called a "leap second." The leap 
  48.  * second is always added as the last second of the day, and always 
  49.  * on December 31 or June 30. For example, the last minute of the 
  50.  * year 1995 was 61 seconds long, thanks to an added leap second. 
  51.  * Most computer clocks are not accurate enough to be able to reflect 
  52.  * the leap-second distinction. 
  53.  * <p>
  54.  * Some computer standards are defined in terms of Greenwich mean 
  55.  * time (GMT), which is equivalent to universal time (UT).  GMT is 
  56.  * the "civil" name for the standard; UT is the 
  57.  * "scientific" name for the same standard. The 
  58.  * distinction between UTC and UT is that UTC is based on an atomic 
  59.  * clock and UT is based on astronomical observations, which for all 
  60.  * practical purposes is an invisibly fine hair to split. Because the 
  61.  * earth's rotation is not uniform (it slows down and speeds up 
  62.  * in complicated ways), UT does not always flow uniformly. Leap 
  63.  * seconds are introduced as needed into UTC so as to keep UTC within 
  64.  * 0.9 seconds of UT1, which is a version of UT with certain 
  65.  * corrections applied. There are other time and date systems as 
  66.  * well; for example, the time scale used by the satellite-based 
  67.  * global positioning system (GPS) is synchronized to UTC but is 
  68.  * <i>not</i> adjusted for leap seconds. An interesting source of 
  69.  * further information is the U.S. Naval Observatory, particularly 
  70.  * the Directorate of Time at:
  71.  * <blockquote><pre>
  72.  *     http://tycho.usno.navy.mil
  73.  * </pre></blockquote>
  74.  * <p>
  75.  * and their definitions of "Systems of Time" at:
  76.  * <blockquote><pre>
  77.  *     http://tycho.usno.navy.mil/systime.html
  78.  * </pre></blockquote>
  79.  * <p>
  80.  * In all methods of class <code>Date</code> that accept or return 
  81.  * year, month, date, hours, minutes, and seconds values, the 
  82.  * following representations are used: 
  83.  * <ul>
  84.  * <li>A year <i>y</i> is represented by the integer 
  85.  *     <i>y</i> <code>- 1900</code>. 
  86.  * <li>A month is represented by an integer form 0 to 11; 0 is January, 
  87.  *     1 is February, and so forth; thus 11 is December. 
  88.  * <li>A date (day of month) is represented by an integer from 1 to 31 
  89.  *     in the usual manner. 
  90.  * <li>An hour is represented by an integer from 0 to 23. Thus, the hour 
  91.  *     from midnight to 1 a.m. is hour 0, and the hour from noon to 1 
  92.  *     p.m. is hour 12. 
  93.  * <li>A minute is represented by an integer from 0 to 59 in the usual manner.
  94.  * <li>A second is represented by an integer from 0 to 61; the values 60 and 
  95.  *     61 occur only for leap seconds and even then only in Java 
  96.  *     implementations that actually track leap seconds correctly. Because 
  97.  *     of the manner in which leap seconds are currently introduced, it is 
  98.  *     extremely unlikely that two leap seconds will occur in the same 
  99.  *     minute, but this specification follows the date and time conventions 
  100.  *     for ISO C.
  101.  * </ul>
  102.  * <p>
  103.  * In all cases, arguments given to methods for these purposes need 
  104.  * not fall within the indicated ranges; for example, a date may be 
  105.  * specified as January 32 and is interpreted as meaning February 1.
  106.  *
  107.  * @author  James Gosling
  108.  * @author  Arthur van Hoff
  109.  * @author  Alan Liu
  110.  * @version 1.52, 03/18/98
  111.  * @see     java.text.DateFormat
  112.  * @see     java.util.Calendar
  113.  * @see     java.util.TimeZone
  114.  * @since   JDK1.0
  115.  */
  116. public class Date implements java.io.Serializable, Cloneable, Comparable {
  117.  
  118.     /* If cal is null, then fastTime indicates the time in millis.
  119.      * Otherwise, fastTime is ignored, and cal indicates the time.
  120.      * The cal object is only created if a setXxx call is made to
  121.      * set a field.  For other operations, staticCal is used instead.
  122.      */
  123.     private transient Calendar cal;
  124.     private transient long fastTime;
  125.  
  126.     private static Calendar staticCal = null;
  127.     private static Calendar utcCal = null;
  128.     private static int defaultCenturyStart = 0;
  129.  
  130.     /* use serialVersionUID from modified java.util.Date for
  131.      * interoperability with JDK1.1. The Date was modified to write
  132.      * and read only the UTC time.
  133.      */
  134.     private static final long serialVersionUID = 7523967970034938905L;
  135.     
  136.     /**
  137.      * Caches for the DateFormatters used by various toString methods.
  138.      */
  139.     private static SoftReference simpleFormatter = null;
  140.     private static SoftReference gmtFormatter = null;
  141.     
  142.     /**
  143.      * Allocates a <code>Date</code> object and initializes it so that 
  144.      * it represents the time at which it was allocated, measured to the 
  145.      * nearest millisecond. 
  146.      *
  147.      * @see     java.lang.System#currentTimeMillis()
  148.      */
  149.     public Date() {
  150.         this(System.currentTimeMillis());
  151.     }
  152.  
  153.     /**
  154.      * Allocates a <code>Date</code> object and initializes it to 
  155.      * represent the specified number of milliseconds since the 
  156.      * standard base time known as "the epoch", namely January 1, 
  157.      * 1970, 00:00:00 GMT. 
  158.      *
  159.      * @param   date   the milliseconds since January 1, 1970, 00:00:00 GMT.
  160.      * @see     java.lang.System#currentTimeMillis()
  161.      */
  162.     public Date(long date) {
  163.         cal = null;
  164.         fastTime = date;
  165.     }
  166.  
  167.     /**
  168.      * Allocates a <code>Date</code> object and initializes it so that 
  169.      * it represents midnight, local time, at the beginning of the day 
  170.      * specified by the <code>year</code>, <code>month</code>, and 
  171.      * <code>date</code> arguments. 
  172.      *
  173.      * @param   year    the year minus 1900.
  174.      * @param   month   the month between 0-11.
  175.      * @param   date    the day of the month between 1-31.
  176.      * @see     java.util.Calendar
  177.      * @deprecated As of JDK version 1.1,
  178.      * replaced by <code>Calendar.set(year + 1900, month, date)</code>
  179.      * or <code>GregorianCalendar(year + 1900, month, date)</code>.
  180.      */
  181.     public Date(int year, int month, int date) {
  182.         this(year, month, date, 0, 0, 0);
  183.     }
  184.  
  185.     /**
  186.      * Allocates a <code>Date</code> object and initializes it so that 
  187.      * it represents the instant at the start of the minute specified by 
  188.      * the <code>year</code>, <code>month</code>, <code>date</code>, 
  189.      * <code>hrs</code>, and <code>min</code> arguments, in the local 
  190.      * time zone. 
  191.      *
  192.      * @param   year    the year minus 1900.
  193.      * @param   month   the month between 0-11.
  194.      * @param   date    the day of the month between 1-31.
  195.      * @param   hrs     the hours between 0-23.
  196.      * @param   min     the minutes between 0-59.
  197.      * @see     java.util.Calendar
  198.      * @deprecated As of JDK version 1.1,
  199.      * replaced by <code>Calendar.set(year + 1900, month, date,
  200.      * hrs, min)</code> or <code>GregorianCalendar(year + 1900,
  201.      * month, date, hrs, min)</code>.
  202.      */
  203.     public Date(int year, int month, int date, int hrs, int min) {
  204.         this(year, month, date, hrs, min, 0);
  205.     }
  206.  
  207.     /**
  208.      * Allocates a <code>Date</code> object and initializes it so that 
  209.      * it represents the instant at the start of the second specified 
  210.      * by the <code>year</code>, <code>month</code>, <code>date</code>, 
  211.      * <code>hrs</code>, <code>min</code>, and <code>sec</code> arguments, 
  212.      * in the local time zone. 
  213.      *
  214.      * @param   year    the year minus 1900.
  215.      * @param   month   the month between 0-11.
  216.      * @param   date    the day of the month between 1-31.
  217.      * @param   hrs     the hours between 0-23.
  218.      * @param   min     the minutes between 0-59.
  219.      * @param   sec     the seconds between 0-59.
  220.      * @see     java.util.Calendar
  221.      * @deprecated As of JDK version 1.1,
  222.      * replaced by <code>Calendar.set(year + 1900, month, date,
  223.      * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
  224.      * month, date, hrs, min, sec)</code>.
  225.      */
  226.     public Date(int year, int month, int date, int hrs, int min, int sec) {
  227.         cal = null;
  228.         if (staticCal == null)
  229.             makeStaticCalendars();
  230.         synchronized (staticCal) {
  231.             staticCal.clear();
  232.             staticCal.set(year + 1900, month, date, hrs, min, sec);
  233.             fastTime = staticCal.getTimeInMillis();
  234.         }
  235.     }
  236.  
  237.     /**
  238.      * Allocates a <code>Date</code> object and initializes it so that 
  239.      * it represents the date and time indicated by the string 
  240.      * <code>s</code>, which is interpreted as if by the 
  241.      * <a href="#parse"><code>parse</code></a> method. 
  242.      *
  243.      * @param   s   a string representation of the date.
  244.      * @see     java.text.DateFormat
  245.      * @see     java.util.Date#parse(java.lang.String)
  246.      * @deprecated As of JDK version 1.1,
  247.      * replaced by <code>DateFormat.parse(String s)</code>.
  248.      */
  249.     public Date(String s) {
  250.         this(parse(s));
  251.     }
  252.  
  253.     /**
  254.      * Determines the date and time based on the arguments. The 
  255.      * arguments are interpreted as a year, month, day of the month, 
  256.      * hour of the day, minute within the hour, and second within the 
  257.      * minute, exactly as for the <tt>Date</tt> constructor with six 
  258.      * arguments, except that the arguments are interpreted relative 
  259.      * to UTC rather than to the local time zone. The time indecated is 
  260.      * returned represented as the distance, measured in milliseconds, 
  261.      * of that time from the epoch (00:00:00 GMT on January 1, 1970).
  262.      *
  263.      * @param   year    the year minus 1900.
  264.      * @param   month   the month between 0-11.
  265.      * @param   date    the day of the month between 1-31.
  266.      * @param   hrs     the hours between 0-23.
  267.      * @param   min     the minutes between 0-59.
  268.      * @param   sec     the seconds between 0-59.
  269.      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT for
  270.      *          the date and time specified by the arguments. 
  271.      * @see     java.util.Calendar
  272.      * @deprecated As of JDK version 1.1,
  273.      * replaced by <code>Calendar.set(year + 1900, month, date,
  274.      * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
  275.      * month, date, hrs, min, sec)</code>, using a UTC
  276.      * <code>TimeZone</code>, followed by <code>Calendar.getTime().getTime()</code>.
  277.      */
  278.     public static long UTC(int year, int month, int date,
  279.                            int hrs, int min, int sec) {
  280.         if (utcCal == null)
  281.             makeStaticCalendars();
  282.         synchronized (utcCal) {
  283.             utcCal.clear();
  284.             utcCal.set(year + 1900, month, date, hrs, min, sec);
  285.             return utcCal.getTimeInMillis();
  286.         }
  287.     }
  288.  
  289.     /**
  290.      * ATtempts to interpret the string <tt>s</tt> as a representation 
  291.      * of a date and time. If the attempt is successful, the time 
  292.      * indicated is returned represented as teh distance, measured in 
  293.      * milliseconds, of that time from the epoch (00:00:00 GMT on 
  294.      * January 1, 1970). If the attempt fails, an 
  295.      * <tt>IllegalArgumentException</tt> is thrown.
  296.      * <p>
  297.      * It accepts many syntaxes; in particular, it recognizes the IETF 
  298.      * standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also 
  299.      * understands the continental U.S. time-zone abbreviations, but for 
  300.      * general use, a time-zone offset should be used: "Sat, 12 Aug 1995 
  301.      * 13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich 
  302.      * meridian). If no time zone is specified, the local time zone is 
  303.      * assumed. GMT and UTC are considered equivalent.
  304.      * <p>
  305.      * The string <tt>s</tt> is processed from left to right, looking for 
  306.      * data of interest. Any material in <tt>s</tt> that is within the 
  307.      * ASCII parenthesis characters <tt>(</tt> and <tt>)</tt> is ignored. 
  308.      * Parentheses may be nested. Otherwise, the only characters permitted 
  309.      * within <tt>s</tt> are these ASCII characters:
  310.      * <blockquote><pre>
  311.      * abcdefghijklmnopqrstuvwxyz
  312.      * ABCDEFGHIJKLMNOPQRSTUVWXYZ
  313.      * 0123456789,+-:/</pre></blockquote>
  314.      * and whitespace characters.<p>
  315.      * A consecutive sequence of decimal digits is treated as a decimal 
  316.      * number:<ul>
  317.      * <li>If a number is preceded by <tt>+</tt> or <tt>-</tt> and a year 
  318.      *     has already been recognized, then the number is a time-zone 
  319.      *     offset. If the number is less than 24, it is an offset measured 
  320.      *     in hours. Otherwise, it is regarded as an offset in minutes, 
  321.      *     expressed in 24-hour time format without punctuation. A 
  322.      *     preceding <tt>-</tt> means a westward offset. Time zone offsets 
  323.      *     are always relative to UTC (Greenwich). Thus, for example, 
  324.      *     <tt>-5</tt> occurring in the string would mean "five hours west 
  325.      *     of Greenwich" and <tt>+0430</tt> would mean "four hours and 
  326.      *     thirty minutes east of Greenwich." It is permitted for the 
  327.      *     string to specify <tt>GMT</tt>, <tt>UT</tt>, or <tt>UTC</tt> 
  328.      *     redundantly-for example, <tt>GMT-5</tt> or <tt>utc+0430</tt>.
  329.      * <li>If a number is greater than 70, it is regarded as a year number. 
  330.      *     It must be followed by a space, comma, slash, or end of string. 
  331.      *     If it is greater than 1900, then 1900 is subtracted from it.
  332.      * <li>If the number is followed by a colon, it is regarded as an hour, 
  333.      *     unless an hour has already been recognized, in which case it is 
  334.      *     regarded as a minute.
  335.      * <li>If the number is followed by a slash, it is regarded as a month 
  336.      *     (it is decreased by 1 to produce a number in the range <tt>0</tt> 
  337.      *     to <tt>11</tt>), unless a month has already been recognized, in 
  338.      *     which case it is regarded as a day of the month.
  339.      * <li>If the number is followed by whitespace, a comma, a hyphen, or 
  340.      *     end of string, then if an hour has been recognized but not a 
  341.      *     minute, it is regarded as a minute; otherwise, if a minute has 
  342.      *     been recognized but not a second, it is regarded as a second; 
  343.      *     otherwise, it is regarded as a day of the month. </ul><p>
  344.      * A consecutive sequence of letters is regarded as a word and treated 
  345.      * as follows:<ul>
  346.      * <li>A word that matches <tt>AM</tt>, ignoring case, is ignored (but 
  347.      *     the parse fails if an hour has not been recognized or is less 
  348.      *     than <tt>1</tt> or greater than <tt>12</tt>).
  349.      * <li>A word that matches <tt>PM</tt>, ignoring case, adds <tt>12</tt> 
  350.      *     to the hour (but the parse fails if an hour has not been 
  351.      *     recognized or is less than <tt>1</tt> or greater than <tt>12</tt>).
  352.      * <li>Any word that matches any prefix of <tt>SUNDAY, MONDAY, TUESDAY, 
  353.      *     WEDNESDAY, THURSDAY, FRIDAY</tt>, or <tt>SATURDAY</tt>, ignoring 
  354.      *     case, is ignored. For example, <tt>sat, Friday, TUE</tt>, and 
  355.      *     <tt>Thurs</tt> are ignored.
  356.      * <li>Otherwise, any word that matches any prefix of <tt>JANUARY, 
  357.      *     FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, 
  358.      *     OCTOBER, NOVEMBER</tt>, or <tt>DECEMBER</tt>, ignoring case, and 
  359.      *     considering them in the order given here, is recognized as
  360.      *     specifying a month and is converted to a number (<tt>0</tt> to 
  361.      *     <tt>11</tt>). For example, <tt>aug, Sept, april</tt>, and 
  362.      *     <tt>NOV</tt> are recognized as months. So is <tt>Ma</tt>, which 
  363.      *     is recognized as <tt>MARCH</tt>, not <tt>MAY</tt>.
  364.      * <li>Any word that matches <tt>GMT, UT</tt>, or <tt>UTC</tt>, ignoring 
  365.      *     case, is treated as referring to UTC. 
  366.      * <li>Any word that matches <tt>EST, CST, MST</tt>, or <tt>PST</tt>, 
  367.      *     ignoring case, is recognized as referring to the time zone in 
  368.      *     North America that is five, six, seven, or eight hours west of 
  369.      *     Greenwich, respectively. Any word that matches <tt>EDT, CDT, 
  370.      *     MDT</tt>, or <tt>PDT</tt>, ignoring case, is recognized as 
  371.      *     referring to the same time zone, respectively, during daylight 
  372.      *     saving time.</ul><p>
  373.      * Once the entire string s has been scanned, it is converted to a time 
  374.      * result in one of two ways. If a time zone or time-zone offset has been 
  375.      * recognized, then the year, month, day of month, hour, minute, and 
  376.      * second are interpreted in UTC and then the time-zone offset is 
  377.      * applied. Otherwise, the year, month, day of month, hour, minute, and 
  378.      * second are interpreted in the local time zone.
  379.      *
  380.      * @param   s   a string to be parsed as a date.
  381.      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
  382.      *          represented by the string argument.
  383.      * @see     java.text.DateFormat
  384.      * @deprecated As of JDK version 1.1,
  385.      * replaced by <code>DateFormat.parse(String s)</code>.
  386.      */
  387.     public static long parse(String s) {
  388.         if (staticCal == null)
  389.             makeStaticCalendars(); // also sets defaultCenturyStart
  390.         
  391.         int year = Integer.MIN_VALUE;
  392.         int mon = -1;
  393.         int mday = -1;
  394.         int hour = -1;
  395.         int min = -1;
  396.         int sec = -1;
  397.         int millis = -1;
  398.         int c = -1;
  399.         int i = 0;
  400.         int n = -1;
  401.         int wst = -1;
  402.         int tzoffset = -1;
  403.         int prevc = 0;
  404.     syntax:
  405.         {
  406.             if (s == null)
  407.                 break syntax;
  408.             int limit = s.length();
  409.             while (i < limit) {
  410.                 c = s.charAt(i);
  411.                 i++;
  412.                 if (c <= ' ' || c == ',')
  413.                     continue;
  414.                 if (c == '(') { // skip comments
  415.                     int depth = 1;
  416.                     while (i < limit) {
  417.                         c = s.charAt(i);
  418.                         i++;
  419.                         if (c == '(') depth++;
  420.                         else if (c == ')')
  421.                             if (--depth <= 0)
  422.                                 break;
  423.                     }
  424.                     continue;
  425.                 }
  426.                 if ('0' <= c && c <= '9') {
  427.                     n = c - '0';
  428.                     while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
  429.                         n = n * 10 + c - '0';
  430.                         i++;
  431.                     }
  432.                     if (prevc == '+' || prevc == '-' && year != Integer.MIN_VALUE) {
  433.                         // timezone offset
  434.                         if (n < 24)
  435.                             n = n * 60; // EG. "GMT-3"
  436.                         else
  437.                             n = n % 100 + n / 100 * 60; // eg "GMT-0430"
  438.                         if (prevc == '+')   // plus means east of GMT
  439.                             n = -n;
  440.                         if (tzoffset != 0 && tzoffset != -1)
  441.                             break syntax;
  442.                         tzoffset = n;
  443.                     } else if (n >= 70)
  444.                         if (year != Integer.MIN_VALUE)
  445.                             break syntax;
  446.                         else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
  447.                             // year = n < 1900 ? n : n - 1900;
  448.                             year = n;
  449.                         else
  450.                             break syntax;
  451.                     else if (c == ':')
  452.                         if (hour < 0)
  453.                             hour = (byte) n;
  454.                         else if (min < 0)
  455.                             min = (byte) n;
  456.                         else
  457.                             break syntax;
  458.                     else if (c == '/')
  459.                         if (mon < 0)
  460.                             mon = (byte) (n - 1);
  461.                         else if (mday < 0)
  462.                             mday = (byte) n;
  463.                         else
  464.                             break syntax;
  465.                     else if (i < limit && c != ',' && c > ' ' && c != '-')
  466.                         break syntax;
  467.                     else if (hour >= 0 && min < 0)
  468.                         min = (byte) n;
  469.                     else if (min >= 0 && sec < 0)
  470.                         sec = (byte) n;
  471.                     else if (mday < 0)
  472.                         mday = (byte) n;
  473.                     // Handle two-digit years < 70 (70-99 handled above).
  474.                     else if (year == Integer.MIN_VALUE && mon >= 0 && mday >= 0)
  475.                         year = n;
  476.                     else
  477.                         break syntax;
  478.                     prevc = 0;
  479.                 } else if (c == '/' || c == ':' || c == '+' || c == '-')
  480.                     prevc = c;
  481.                 else {
  482.                     int st = i - 1;
  483.                     while (i < limit) {
  484.                         c = s.charAt(i);
  485.                         if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'))
  486.                             break;
  487.                         i++;
  488.                     }
  489.                     if (i <= st + 1)
  490.                         break syntax;
  491.                     int k;
  492.                     for (k = wtb.length; --k >= 0;)
  493.                         if (wtb[k].regionMatches(true, 0, s, st, i - st)) {
  494.                             int action = ttb[k];
  495.                             if (action != 0) {
  496.                                 if (action == 1) {  // pm
  497.                                     if (hour > 12 || hour < 1)
  498.                                         break syntax;
  499.                                     else if (hour < 12)
  500.                                         hour += 12;
  501.                                 } else if (action == 14) {  // am
  502.                                     if (hour > 12 || hour < 1)
  503.                                         break syntax;
  504.                                     else if (hour == 12)
  505.                                         hour = 0;
  506.                                 } else if (action <= 13) {  // month!
  507.                                     if (mon < 0)
  508.                                         mon = (byte) (action - 2);
  509.                                     else
  510.                                         break syntax;
  511.                                 } else {
  512.                                     tzoffset = action - 10000;
  513.                                 }
  514.                             }
  515.                             break;
  516.                         }
  517.                     if (k < 0)
  518.                         break syntax;
  519.                     prevc = 0;
  520.                 }
  521.             }
  522.             if (year == Integer.MIN_VALUE || mon < 0 || mday < 0)
  523.                 break syntax;
  524.             // Parse 2-digit years within the correct default century.
  525.             if (year < 100) {
  526.                 year += (defaultCenturyStart / 100) * 100;
  527.                 if (year < defaultCenturyStart) year += 100;
  528.             }
  529.             year -= 1900;
  530.             if (sec < 0)
  531.                 sec = 0;
  532.             if (min < 0)
  533.                 min = 0;
  534.             if (hour < 0)
  535.                 hour = 0;
  536.             if (tzoffset == -1) // no time zone specified, have to use local
  537.                 return new Date (year, mon, mday, hour, min, sec).getTime();
  538.             return UTC(year, mon, mday, hour, min, sec) + tzoffset * (60 * 1000);
  539.         }
  540.         // syntax error
  541.         throw new IllegalArgumentException();
  542.     }
  543.     private final static String wtb[] = {
  544.         "am", "pm",
  545.         "monday", "tuesday", "wednesday", "thursday", "friday",
  546.         "saturday", "sunday",
  547.         "january", "february", "march", "april", "may", "june",
  548.         "july", "august", "september", "october", "november", "december",
  549.         "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
  550.         "mst", "mdt", "pst", "pdt"
  551.         // this time zone table needs to be expanded
  552.     };
  553.     private final static int ttb[] = {
  554.         14, 1, 0, 0, 0, 0, 0, 0, 0,
  555.         2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
  556.         10000 + 0, 10000 + 0, 10000 + 0,    // GMT/UT/UTC
  557.         10000 + 5 * 60, 10000 + 4 * 60, // EST/EDT
  558.         10000 + 6 * 60, 10000 + 5 * 60,
  559.         10000 + 7 * 60, 10000 + 6 * 60,
  560.         10000 + 8 * 60, 10000 + 7 * 60
  561.     };
  562.  
  563.     /**
  564.      * Returns a value that is the result of subtracting 1900 from the 
  565.      * year that contains or begins with the instant in time represented 
  566.      * by this <code>Date</code> object, as interpreted in the local 
  567.      * time zone.
  568.      *
  569.      * @return  the year represented by this date, minus 1900.
  570.      * @see     java.util.Calendar
  571.      * @deprecated As of JDK version 1.1,
  572.      * replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>.
  573.      */
  574.     public int getYear() {
  575.         return getField(Calendar.YEAR) - 1900;
  576.     }
  577.  
  578.     /**
  579.      * Sets the year of this <tt>Date</tt> object to be the specified 
  580.      * value plus 1900. This <code>Date</code> object is modified so 
  581.      * that it represents a point in time within the specified year, 
  582.      * with the month, date, hour, minute, and second the same as 
  583.      * before, as interpreted in the local time zone. (Of course, if 
  584.      * the date was February 29, for example, and the year is set to a 
  585.      * non-leap year, then the new date will be treated as if it were 
  586.      * on March 1.)
  587.      *
  588.      * @param   year    the year value.
  589.      * @see     java.util.Calendar
  590.      * @deprecated As of JDK version 1.1,
  591.      * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>.
  592.      */
  593.     public void setYear(int year) {
  594.         setField(Calendar.YEAR, year + 1900);
  595.     }
  596.  
  597.     /**
  598.      * Returns a number representing the month that contains or begins 
  599.      * with the instant in time represented by this <tt>Date</tt> object. 
  600.      * The value returned is between <code>0</code> and <code>11</code>, 
  601.      * with the value <code>0</code> representing January.
  602.      *
  603.      * @return  the month represented by this date.
  604.      * @see     java.util.Calendar
  605.      * @deprecated As of JDK version 1.1,
  606.      * replaced by <code>Calendar.get(Calendar.MONTH)</code>.
  607.      */
  608.     public int getMonth() {
  609.         return getField(Calendar.MONTH);
  610.     }
  611.  
  612.     /**
  613.      * Sets the month of this date to the specified value. This 
  614.      * <tt>Date</tt> object is modified so that it represents a point 
  615.      * in time within the specified month, with the year, date, hour, 
  616.      * minute, and second the same as before, as interpreted in the 
  617.      * local time zone. If the date was October 31, for example, and 
  618.      * the month is set to June, then the new date will be treated as 
  619.      * if it were on July 1, because June has only 30 days.
  620.      *
  621.      * @param   month   the month value between 0-11.
  622.      * @see     java.util.Calendar
  623.      * @deprecated As of JDK version 1.1,
  624.      * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>.
  625.      */
  626.     public void setMonth(int month) {
  627.         setField(Calendar.MONTH, month);
  628.     }
  629.  
  630.     /**
  631.      * Returns the day of the month represented by this <tt>Date</tt> object. 
  632.      * The value returned is between <code>1</code> and <code>31</code> 
  633.      * representing the day of the month that contains or begins with the 
  634.      * instant in time represented by this <tt>Date</tt> object, as 
  635.      * interpreted in the local time zone.
  636.      *
  637.      * @return  the day of the month represented by this date.
  638.      * @see     java.util.Calendar
  639.      * @deprecated As of JDK version 1.1,
  640.      * replaced by <code>Calendar.get(Calendar.DAY_OF_MONTH)</code>.
  641.      * @deprecated
  642.      */
  643.     public int getDate() {
  644.         return getField(Calendar.DATE);
  645.     }
  646.  
  647.     /**
  648.      * Sets the day of the month of this <tt>Date</tt> object to the 
  649.      * specified value. This <tt>Date</tt> object is modified so that 
  650.      * it represents a point in time within the specified day of the 
  651.      * month, with the year, month, hour, minute, and second the same 
  652.      * as before, as interpreted in the local time zone. If the date 
  653.      * was April 30, for example, and the date is set to 31, then it 
  654.      * will be treated as if it were on May 1, because April has only 
  655.      * 30 days.
  656.      *
  657.      * @param   date   the day of the month value between 1-31.
  658.      * @see     java.util.Calendar
  659.      * @deprecated As of JDK version 1.1,
  660.      * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>.
  661.      */
  662.     public void setDate(int date) {
  663.         setField(Calendar.DATE, date);
  664.     }
  665.  
  666.     /**
  667.      * Returns the day of the week represented by this date. The 
  668.      * returned value (<tt>0</tt> = Sunday, <tt>1</tt> = Monday, 
  669.      * <tt>2</tt> = Tuesday, <tt>3</tt> = Wednesday, <tt>4</tt> = 
  670.      * Thursday, <tt>5</tt> = Friday, <tt>6</tt> = Saturday) 
  671.      * represents the day of the week that contains or begins with 
  672.      * the instant in time represented by this <tt>Date</tt> object, 
  673.      * as interpreted in the local time zone.
  674.      *
  675.      * @return  the day of the week represented by this date.
  676.      * @see     java.util.Calendar
  677.      * @deprecated As of JDK version 1.1,
  678.      * replaced by <code>Calendar.get(Calendar.DAY_OF_WEEK)</code>.
  679.      */
  680.     public int getDay() {
  681.         return getField(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
  682.     }
  683.  
  684.     /**
  685.      * Returns the hour represented by this <tt>Date</tt> object. The 
  686.      * returned value is a number (<tt>0</tt> through <tt>23</tt>) 
  687.      * representing the hour within the day that contains or begins 
  688.      * with the instant in time represented by this <tt>Date</tt> 
  689.      * object, as interpreted in the local time zone.
  690.      *
  691.      * @return  the hour represented by this date.
  692.      * @see     java.util.Calendar
  693.      * @deprecated As of JDK version 1.1,
  694.      * replaced by <code>Calendar.get(Calendar.HOUR_OF_DAY)</code>.
  695.      */
  696.     public int getHours() {
  697.         return getField(Calendar.HOUR_OF_DAY);
  698.     }
  699.  
  700.     /**
  701.      * Sets the hour of this <tt>Date</tt> object to the specified value. 
  702.      * This <tt>Date</tt> object is modified so that it represents a point 
  703.      * in time within the specified hour of the day, with the year, month, 
  704.      * date, minute, and second the same as before, as interpreted in the 
  705.      * local time zone.
  706.      *
  707.      * @param   hours   the hour value.
  708.      * @see     java.util.Calendar
  709.      * @deprecated As of JDK version 1.1,
  710.      * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>.
  711.      */
  712.     public void setHours(int hours) {
  713.         setField(Calendar.HOUR_OF_DAY, hours);
  714.     }
  715.  
  716.     /**
  717.      * Returns the number of minutes past the hour represented by this date, 
  718.      * as interpreted in the local time zone. 
  719.      * The value returned is between <code>0</code> and <code>59</code>.
  720.      *
  721.      * @return  the number of minutes past the hour represented by this date.
  722.      * @see     java.util.Calendar
  723.      * @deprecated As of JDK version 1.1,
  724.      * replaced by <code>Calendar.get(Calendar.MINUTE)</code>.
  725.      */
  726.     public int getMinutes() {
  727.         return getField(Calendar.MINUTE);
  728.     }
  729.  
  730.     /**
  731.      * Sets the minutes of this <tt>Date</tt> object to the specified value. 
  732.      * This <tt>Date</tt> object is modified so that it represents a point 
  733.      * in time within the specified minute of the hour, with the year, month, 
  734.      * date, hour, and second the same as before, as interpreted in the 
  735.      * local time zone.
  736.      *
  737.      * @param   minutes   the value of the minutes.
  738.      * @see     java.util.Calendar
  739.      * @deprecated As of JDK version 1.1,
  740.      * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>.
  741.      */
  742.     public void setMinutes(int minutes) {
  743.         setField(Calendar.MINUTE, minutes);
  744.     }
  745.  
  746.     /**
  747.      * Returns the number of seconds past the minute represented by this date.
  748.      * The value returned is between <code>0</code> and <code>61</code>. The
  749.      * values <code>60</code> and <code>61</code> can only occur on those 
  750.      * Java Virtual Machines that take leap seconds into account.
  751.      *
  752.      * @return  the number of seconds past the minute represented by this date.
  753.      * @see     java.util.Calendar
  754.      * @deprecated As of JDK version 1.1,
  755.      * replaced by <code>Calendar.get(Calendar.SECOND)</code>.
  756.      */
  757.     public int getSeconds() {
  758.         return getField(Calendar.SECOND);
  759.     }
  760.  
  761.     /**
  762.      * Sets the seconds of this <tt>Date</tt> to the specified value. 
  763.      * This <tt>Date</tt> object is modified so that it represents a 
  764.      * point in time within the specified second of the minute, with 
  765.      * the year, month, date, hour, and minute the same as before, as 
  766.      * interpreted in the local time zone.
  767.      *
  768.      * @param   seconds   the seconds value.
  769.      * @see     java.util.Calendar
  770.      * @deprecated As of JDK version 1.1,
  771.      * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>. 
  772.      */
  773.     public void setSeconds(int seconds) {
  774.         setField(Calendar.SECOND, seconds);
  775.     }
  776.  
  777.     /**
  778.      * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
  779.      * represented by this <tt>Date</tt> object.
  780.      *
  781.      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
  782.      *          represented by this date.
  783.      */
  784.     public long getTime() {
  785.         return (cal == null) ? fastTime : cal.getTimeInMillis();
  786.     }
  787.  
  788.     /**
  789.      * Sets this <tt>Date</tt> object to represent a point in time that is 
  790.      * <tt>time</tt> milliseconds after January 1, 1970 00:00:00 GMT. 
  791.      *
  792.      * @param   time   the number of milliseconds.
  793.      */
  794.     public void setTime(long time) {
  795.         if (cal == null) {
  796.             fastTime = time;
  797.         }
  798.         else {
  799.             cal.setTimeInMillis(time);
  800.         }
  801.     }
  802.  
  803.     /**
  804.      * Tests if this date is before the specified date.
  805.      *
  806.      * @param   when   a date.
  807.      * @return  <code>true</code> if and only if the instant of time 
  808.      *            represented by this <tt>Date</tt> object is strictly 
  809.      *            earlier than the instant represented by <tt>when</tt>;
  810.      *          <code>false</code> otherwise.
  811.      */
  812.     public boolean before(Date when) {
  813.         return getTime() < when.getTime();
  814.     }
  815.  
  816.     /**
  817.      * Tests if this date is after the specified date.
  818.      *
  819.      * @param   when   a date.
  820.      * @return  <code>true</code> if and only if the instant represented 
  821.      *          by this <tt>Date</tt> object is strictly later than the 
  822.      *          instant represented by <tt>when</tt>; 
  823.      *          <code>false</code> otherwise.
  824.      */
  825.     public boolean after(Date when) {
  826.         return getTime() > when.getTime();
  827.     }
  828.  
  829.     /**
  830.      * Compares two dates for equality.
  831.      * The result is <code>true</code> if and only if the argument is 
  832.      * not <code>null</code> and is a <code>Date</code> object that 
  833.      * represents the same point in time, to the millisecond, as this object.
  834.      * <p>
  835.      * Thus, two <code>Date</code> objects are equal if and only if the 
  836.      * <code>getTime</code> method returns the same <code>long</code> 
  837.      * value for both. 
  838.      *
  839.      * @param   obj   the object to compare with.
  840.      * @return  <code>true</code> if the objects are the same;
  841.      *          <code>false</code> otherwise.
  842.      * @see     java.util.Date#getTime()
  843.      */
  844.     public boolean equals(Object obj) {
  845.         return obj != null && obj instanceof Date && getTime() == ((Date) obj).getTime();
  846.     }
  847.  
  848.     /**
  849.      * Compares two Dates for ordering.
  850.      *
  851.      * @param   anotherDate   the <code>Date</code> to be compared.
  852.      * @return  the value <code>0</code> if the argument Date is equal to
  853.      *          this Date; a value less than <code>0</code> if this Date
  854.      *          is before the Date argument; and a value greater than
  855.      *        <code>0</code> if this Date is after the Date argument.
  856.      * @since   JDK1.2
  857.      */
  858.     public int compareTo(Date anotherDate) {
  859.     long thisTime = this.getTime();
  860.     long anotherTime = anotherDate.getTime();
  861.     return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
  862.     }
  863.  
  864.     /**
  865.      * Compares this Date to another Object.  If the Object is a Date,
  866.      * this function behaves like <code>compareTo(Date)</code>.  Otherwise,
  867.      * it throws a <code>ClassCastException</code> (as Dates are comparable
  868.      * only to other Dates).
  869.      *
  870.      * @param   o the <code>Object</code> to be compared.
  871.      * @return  the value <code>0</code> if the argument is a Date
  872.      *        equal to this Date; a value less than <code>0</code> if the
  873.      *        argument is a Date after this Date; and a value greater than
  874.      *        <code>0</code> if the argument is a Date before this Date.
  875.      * @exception ClassCastException if the argument is not a
  876.      *          <code>Date</code>. 
  877.      * @see     java.lang.Comparable
  878.      * @since   JDK1.2
  879.      */
  880.     public int compareTo(Object o) {
  881.     return compareTo((Date)o);
  882.     }
  883.  
  884.     /**
  885.      * Returns a hash code value for this object. The result is the 
  886.      * exclusive OR of the two halves of the primitive <tt>long</tt> 
  887.      * value returned by the <a href="#getTime"><tt>getTime</tt></a> 
  888.      * method. That is, the hash code is the value of the expression:
  889.      * <blockquote><pre>
  890.      * (int)(this.getTime()^(this.getTime() >>> 32))</pre></blockquote>
  891.      *
  892.      * @return  a hash code value for this object. 
  893.      */
  894.     public int hashCode() {
  895.         long ht = getTime();
  896.         return (int) ht ^ (int) (ht >> 32);
  897.     }
  898.  
  899.     /**
  900.      * Converts this <code>Date</code> object to a <code>String</code> 
  901.      * of the form:
  902.      * <blockquote><pre>
  903.      * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
  904.      * where:<ul>
  905.      * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed, 
  906.      *     Thu, Fri, Sat</tt>).
  907.      * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, 
  908.      *     Jul, Aug, Sep, Oct, Nov, Dec</tt>).
  909.      * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through 
  910.      *     <tt>31</tt>), as two decimal digits.
  911.      * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through 
  912.      *     <tt>23</tt>), as two decimal digits.
  913.      * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through 
  914.      *     <tt>59</tt>), as two decimal digits.
  915.      * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through 
  916.      *     <tt>61</tt>, as two decimal digits.
  917.      * <li><tt>zzz</tt> is the time zone (and may reflect daylight savings 
  918.      *     time). Standard time zone abbreviations include those 
  919.      *     recognized by the method <tt>parse</tt>. If time zone 
  920.      *     informationi is not available, then <tt>zzz</tt> is empty - 
  921.      *     that is, it consists of no characters at all.
  922.      * <li><tt>yyyy</tt> is the year, as four decimal digits.
  923.      * </ul>
  924.      *
  925.      * @return  a string representation of this date. 
  926.      * @see     java.util.Date#toLocaleString()
  927.      * @see     java.util.Date#toGMTString()
  928.      */
  929.     public String toString() {
  930.     DateFormat formatter = null;
  931.     if (simpleFormatter != null) {
  932.         formatter = (DateFormat)simpleFormatter.get();
  933.     }
  934.     if (formatter == null) {
  935.         /* No cache yet, or cached formatter GC'd */
  936.         formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy",
  937.                          Locale.US);
  938.         simpleFormatter = new SoftReference(formatter);
  939.     }
  940.         synchronized (formatter) {
  941.             formatter.setTimeZone(TimeZone.getDefault());
  942.             return formatter.format(this);
  943.         }
  944.     }
  945.  
  946.     /**
  947.      * Creates a string representation of this <ttt>Date</tt> object in an 
  948.      * implementation-dependent form. The intent is that the form should 
  949.      * be familiar to the user of the Java application, wherever it may 
  950.      * happen to be running. The intent is comparable to that of the 
  951.      * "<code>%c</code>" format supported by the <code>strftime()</code> 
  952.      * function of ISO C. 
  953.      *
  954.      * @return  a string representation of this date, using the locale
  955.      *          conventions.
  956.      * @see     java.text.DateFormat
  957.      * @see     java.util.Date#toString()
  958.      * @see     java.util.Date#toGMTString()
  959.      * @deprecated As of JDK version 1.1,
  960.      * replaced by <code>DateFormat.format(Date date)</code>.
  961.      */
  962.     public String toLocaleString() {
  963.     DateFormat formatter = DateFormat.getDateTimeInstance();
  964.     formatter.setTimeZone(TimeZone.getDefault());
  965.     return formatter.format(this);
  966.     }
  967.  
  968.     /**
  969.      * Creates a string representation of this <tt>Date</tt> object of 
  970.      * the form:
  971.      * <blockquote<pre>
  972.      * d mon yyyy hh:mm:ss GMT</pre></blockquote>
  973.      * where:<ul>
  974.      * <li><i>d</i> is the day of the month (<tt>1</tt> through <tt>31</tt>), 
  975.      *     as one or two decimal digits.
  976.      * <li><i>mon</i> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, Jul, 
  977.      *     Aug, Sep, Oct, Nov, Dec</tt>).
  978.      * <li><i>yyyy</i> i sthe year, as four decimal digits.
  979.      * <li><i>hh</i> is the hour of the day (<tt>00</tt> through <tt>23</tt>), 
  980.      *     as two decimal digits.
  981.      * <li><i>mm</i> is the minute within the hour (<tt>00</tt> through 
  982.      *     <tt>59</tt>), as two decimal digits.
  983.      * <li><i>ss</i> is the second within the minute (<tt>00</tt> through 
  984.      *     <tt>61</tt>), as two decimal digits.
  985.      * <li><i>GMT</i> is exactly the ASCII letters "<tt>GMT</tt>" to indicate 
  986.      *     Greenwich Mean Time.
  987.      * </ul><p>
  988.      * The result does not depend on the local time zone.
  989.      * 
  990.      * @return  a string representation of this date, using the Internet GMT
  991.      *          conventions.
  992.      * @see     java.text.DateFormat
  993.      * @see     java.util.Date#toString()
  994.      * @see     java.util.Date#toLocaleString()
  995.      * @deprecated As of JDK version 1.1,
  996.      * replaced by <code>DateFormat.format(Date date)</code>, using a
  997.      * GMT <code>TimeZone</code>.
  998.      */
  999.     public String toGMTString() {
  1000.     DateFormat formatter = null;
  1001.     if (gmtFormatter != null) {
  1002.         formatter = (DateFormat)gmtFormatter.get();
  1003.     }
  1004.     if (formatter == null) {
  1005.         /* No cache yet, or cached formatter GC'd */
  1006.         formatter = new SimpleDateFormat("d MMM yyyy HH:mm:ss 'GMT'", 
  1007.                          Locale.US);
  1008.             formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
  1009.         gmtFormatter = new SoftReference(formatter);
  1010.     }
  1011.         return formatter.format(this);
  1012.     }
  1013.  
  1014.     /**
  1015.      * Returns the offset, measured in minutes, for the local time zone 
  1016.      * relative to UTC that is appropriate for the time represented by 
  1017.      * this <tt>Date</tt> object.<p>
  1018.      * For example, in Massachusetts, five time zones west of Greenwich:
  1019.      * <blockquote><pre>
  1020.      * new Date(96, 1, 14).getTimezoneOffset() returns 300</pre></blockquote>
  1021.      * because on February 14, 1996, standard time (Eastern Standard Time) 
  1022.      * is in use, which is offset five hours from UTC; but:
  1023.      * <blockquote><pre>
  1024.      * new Date(96, 5, 1).getTimezoneOffset() returns 240</pre></blockquote>
  1025.      * because on May 1, 1996, daylight savings time (Eastern Daylight Time) 
  1026.      * is in use, which is offset only four hours from UTC.<p>
  1027.      * This method produces teh same result as if it computed:
  1028.      * <blockquote><pre>
  1029.      * (this.getTime() - UTC(this.getYear(), 
  1030.      *                       this.getMonth(), 
  1031.      *                       this.getDate(),
  1032.      *                       this.getHours(), 
  1033.      *                       this.getMinutes(), 
  1034.      *                       this.getSeconds())) / (60 * 1000)
  1035.      * </pre></blockquote>
  1036.      *
  1037.      * @return  the time-zone offset, in minutes, for the current locale.
  1038.      * @see     java.util.Calendar
  1039.      * @see     java.util.TimeZone
  1040.      * @deprecated As of JDK version 1.1,
  1041.      * replaced by <code>Calendar.get(Calendar.ZONE_OFFSET) +
  1042.      * Calendar.get(Calendar.DST_OFFSET)</code>.
  1043.      */
  1044.     public int getTimezoneOffset() {
  1045.         int offset;
  1046.         if (cal == null) {
  1047.             if (staticCal == null)
  1048.                 makeStaticCalendars();
  1049.             synchronized (staticCal) {
  1050.                 staticCal.setTimeInMillis(getTime());
  1051.                 offset = staticCal.get(Calendar.ZONE_OFFSET) +
  1052.                     staticCal.get(Calendar.DST_OFFSET);
  1053.             }
  1054.         }
  1055.         else {
  1056.             offset = cal.get(Calendar.ZONE_OFFSET) +
  1057.                 cal.get(Calendar.DST_OFFSET);
  1058.         }
  1059.         return -(offset / 1000 / 60);  // convert to minutes
  1060.     }
  1061.  
  1062.     /**
  1063.      * WriteObject is called to save the Date to a stream.
  1064.      * The UTC time is written to the stream as a long.
  1065.      */
  1066.     private void writeObject(ObjectOutputStream s)
  1067.          throws IOException
  1068.     {
  1069.         s.writeLong(getTime());
  1070.     }
  1071.  
  1072.     /**
  1073.      * readObject is called to restore a date from the stream.
  1074.      * The UTC time is read and the date set from it.
  1075.      */
  1076.     private void readObject(ObjectInputStream s)
  1077.          throws IOException, ClassNotFoundException
  1078.     {
  1079.         fastTime = s.readLong();
  1080.         // we expect to have cal == null here
  1081.     }
  1082.  
  1083.     /**
  1084.      * Return a field for this date by looking it up in a Calendar object.
  1085.      *
  1086.      * @return the field value
  1087.      * @see    java.util.Calendar
  1088.      * @param  field the field to return
  1089.      */
  1090.     private final int getField(int field) {
  1091.         if (cal == null) {
  1092.             if (staticCal == null)
  1093.                 makeStaticCalendars();
  1094.             synchronized (staticCal) {
  1095.                 staticCal.setTimeInMillis(fastTime);
  1096.                 return staticCal.get(field);
  1097.             }
  1098.         }
  1099.         else {
  1100.             return cal.get(field);
  1101.         }
  1102.     }
  1103.  
  1104.     /**
  1105.      * Set a field for this day.
  1106.      *
  1107.      * @param field the field to set
  1108.      * @param value the value to set it to
  1109.      * @see java.util.Calendar
  1110.      */
  1111.     private final void setField(int field, int value) {
  1112.         if (cal == null) {
  1113.             cal = new GregorianCalendar();
  1114.             cal.setTimeInMillis(fastTime);
  1115.         }
  1116.         cal.set(field, value);
  1117.     }
  1118.  
  1119.     private static void makeStaticCalendars() {
  1120.     staticCal = new GregorianCalendar();
  1121.         utcCal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
  1122.         defaultCenturyStart = staticCal.get(Calendar.YEAR) - 80;
  1123.     }
  1124. }
  1125.