rt/emul/compact/src/main/java/java/util/Date.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 04 Oct 2013 12:01:56 +0200
changeset 1340 41046f76a76a
parent 1334 588d5bf7a560
permissions -rw-r--r--
Somehow implementing the calendar classes so they compile
     1 /*
     2  * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.util;
    27 
    28 import java.text.DateFormat;
    29 import java.io.IOException;
    30 import java.io.ObjectOutputStream;
    31 import java.io.ObjectInputStream;
    32 
    33 /**
    34  * The class <code>Date</code> represents a specific instant
    35  * in time, with millisecond precision.
    36  * <p>
    37  * Prior to JDK&nbsp;1.1, the class <code>Date</code> had two additional
    38  * functions.  It allowed the interpretation of dates as year, month, day, hour,
    39  * minute, and second values.  It also allowed the formatting and parsing
    40  * of date strings.  Unfortunately, the API for these functions was not
    41  * amenable to internationalization.  As of JDK&nbsp;1.1, the
    42  * <code>Calendar</code> class should be used to convert between dates and time
    43  * fields and the <code>DateFormat</code> class should be used to format and
    44  * parse date strings.
    45  * The corresponding methods in <code>Date</code> are deprecated.
    46  * <p>
    47  * Although the <code>Date</code> class is intended to reflect
    48  * coordinated universal time (UTC), it may not do so exactly,
    49  * depending on the host environment of the Java Virtual Machine.
    50  * Nearly all modern operating systems assume that 1&nbsp;day&nbsp;=
    51  * 24&nbsp;&times;&nbsp;60&nbsp;&times;&nbsp;60&nbsp;= 86400 seconds
    52  * in all cases. In UTC, however, about once every year or two there
    53  * is an extra second, called a "leap second." The leap
    54  * second is always added as the last second of the day, and always
    55  * on December 31 or June 30. For example, the last minute of the
    56  * year 1995 was 61 seconds long, thanks to an added leap second.
    57  * Most computer clocks are not accurate enough to be able to reflect
    58  * the leap-second distinction.
    59  * <p>
    60  * Some computer standards are defined in terms of Greenwich mean
    61  * time (GMT), which is equivalent to universal time (UT).  GMT is
    62  * the "civil" name for the standard; UT is the
    63  * "scientific" name for the same standard. The
    64  * distinction between UTC and UT is that UTC is based on an atomic
    65  * clock and UT is based on astronomical observations, which for all
    66  * practical purposes is an invisibly fine hair to split. Because the
    67  * earth's rotation is not uniform (it slows down and speeds up
    68  * in complicated ways), UT does not always flow uniformly. Leap
    69  * seconds are introduced as needed into UTC so as to keep UTC within
    70  * 0.9 seconds of UT1, which is a version of UT with certain
    71  * corrections applied. There are other time and date systems as
    72  * well; for example, the time scale used by the satellite-based
    73  * global positioning system (GPS) is synchronized to UTC but is
    74  * <i>not</i> adjusted for leap seconds. An interesting source of
    75  * further information is the U.S. Naval Observatory, particularly
    76  * the Directorate of Time at:
    77  * <blockquote><pre>
    78  *     <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a>
    79  * </pre></blockquote>
    80  * <p>
    81  * and their definitions of "Systems of Time" at:
    82  * <blockquote><pre>
    83  *     <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a>
    84  * </pre></blockquote>
    85  * <p>
    86  * In all methods of class <code>Date</code> that accept or return
    87  * year, month, date, hours, minutes, and seconds values, the
    88  * following representations are used:
    89  * <ul>
    90  * <li>A year <i>y</i> is represented by the integer
    91  *     <i>y</i>&nbsp;<code>-&nbsp;1900</code>.
    92  * <li>A month is represented by an integer from 0 to 11; 0 is January,
    93  *     1 is February, and so forth; thus 11 is December.
    94  * <li>A date (day of month) is represented by an integer from 1 to 31
    95  *     in the usual manner.
    96  * <li>An hour is represented by an integer from 0 to 23. Thus, the hour
    97  *     from midnight to 1 a.m. is hour 0, and the hour from noon to 1
    98  *     p.m. is hour 12.
    99  * <li>A minute is represented by an integer from 0 to 59 in the usual manner.
   100  * <li>A second is represented by an integer from 0 to 61; the values 60 and
   101  *     61 occur only for leap seconds and even then only in Java
   102  *     implementations that actually track leap seconds correctly. Because
   103  *     of the manner in which leap seconds are currently introduced, it is
   104  *     extremely unlikely that two leap seconds will occur in the same
   105  *     minute, but this specification follows the date and time conventions
   106  *     for ISO C.
   107  * </ul>
   108  * <p>
   109  * In all cases, arguments given to methods for these purposes need
   110  * not fall within the indicated ranges; for example, a date may be
   111  * specified as January 32 and is interpreted as meaning February 1.
   112  *
   113  * @author  James Gosling
   114  * @author  Arthur van Hoff
   115  * @author  Alan Liu
   116  * @see     java.text.DateFormat
   117  * @see     java.util.Calendar
   118  * @see     java.util.TimeZone
   119  * @since   JDK1.0
   120  */
   121 public class Date
   122     implements java.io.Serializable, Cloneable, Comparable<Date>
   123 {
   124     private static final BaseCalendar gcal = new BaseCalendar();
   125                                 
   126     private static BaseCalendar jcal;
   127 
   128     private transient long fastTime;
   129 
   130     /*
   131      * If cdate is null, then fastTime indicates the time in millis.
   132      * If cdate.isNormalized() is true, then fastTime and cdate are in
   133      * synch. Otherwise, fastTime is ignored, and cdate indicates the
   134      * time.
   135      */
   136     private transient BaseCalendar.Datum cdate;
   137 
   138     // Initialized just before the value is used. See parse().
   139     private static int defaultCenturyStart;
   140 
   141     /* use serialVersionUID from modified java.util.Date for
   142      * interoperability with JDK1.1. The Date was modified to write
   143      * and read only the UTC time.
   144      */
   145     private static final long serialVersionUID = 7523967970034938905L;
   146 
   147     /**
   148      * Allocates a <code>Date</code> object and initializes it so that
   149      * it represents the time at which it was allocated, measured to the
   150      * nearest millisecond.
   151      *
   152      * @see     java.lang.System#currentTimeMillis()
   153      */
   154     public Date() {
   155         this(System.currentTimeMillis());
   156     }
   157 
   158     /**
   159      * Allocates a <code>Date</code> object and initializes it to
   160      * represent the specified number of milliseconds since the
   161      * standard base time known as "the epoch", namely January 1,
   162      * 1970, 00:00:00 GMT.
   163      *
   164      * @param   date   the milliseconds since January 1, 1970, 00:00:00 GMT.
   165      * @see     java.lang.System#currentTimeMillis()
   166      */
   167     public Date(long date) {
   168         fastTime = date;
   169     }
   170 
   171     /**
   172      * Allocates a <code>Date</code> object and initializes it so that
   173      * it represents midnight, local time, at the beginning of the day
   174      * specified by the <code>year</code>, <code>month</code>, and
   175      * <code>date</code> arguments.
   176      *
   177      * @param   year    the year minus 1900.
   178      * @param   month   the month between 0-11.
   179      * @param   date    the day of the month between 1-31.
   180      * @see     java.util.Calendar
   181      * @deprecated As of JDK version 1.1,
   182      * replaced by <code>Calendar.set(year + 1900, month, date)</code>
   183      * or <code>GregorianCalendar(year + 1900, month, date)</code>.
   184      */
   185     @Deprecated
   186     public Date(int year, int month, int date) {
   187         this(year, month, date, 0, 0, 0);
   188     }
   189 
   190     /**
   191      * Allocates a <code>Date</code> object and initializes it so that
   192      * it represents the instant at the start of the minute specified by
   193      * the <code>year</code>, <code>month</code>, <code>date</code>,
   194      * <code>hrs</code>, and <code>min</code> arguments, in the local
   195      * time zone.
   196      *
   197      * @param   year    the year minus 1900.
   198      * @param   month   the month between 0-11.
   199      * @param   date    the day of the month between 1-31.
   200      * @param   hrs     the hours between 0-23.
   201      * @param   min     the minutes between 0-59.
   202      * @see     java.util.Calendar
   203      * @deprecated As of JDK version 1.1,
   204      * replaced by <code>Calendar.set(year + 1900, month, date,
   205      * hrs, min)</code> or <code>GregorianCalendar(year + 1900,
   206      * month, date, hrs, min)</code>.
   207      */
   208     @Deprecated
   209     public Date(int year, int month, int date, int hrs, int min) {
   210         this(year, month, date, hrs, min, 0);
   211     }
   212 
   213     /**
   214      * Allocates a <code>Date</code> object and initializes it so that
   215      * it represents the instant at the start of the second specified
   216      * by the <code>year</code>, <code>month</code>, <code>date</code>,
   217      * <code>hrs</code>, <code>min</code>, and <code>sec</code> arguments,
   218      * in the local time zone.
   219      *
   220      * @param   year    the year minus 1900.
   221      * @param   month   the month between 0-11.
   222      * @param   date    the day of the month between 1-31.
   223      * @param   hrs     the hours between 0-23.
   224      * @param   min     the minutes between 0-59.
   225      * @param   sec     the seconds between 0-59.
   226      * @see     java.util.Calendar
   227      * @deprecated As of JDK version 1.1,
   228      * replaced by <code>Calendar.set(year + 1900, month, date,
   229      * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
   230      * month, date, hrs, min, sec)</code>.
   231      */
   232     @Deprecated
   233     public Date(int year, int month, int date, int hrs, int min, int sec) {
   234         int y = year + 1900;
   235         // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
   236         if (month >= 12) {
   237             y += month / 12;
   238             month %= 12;
   239         } else if (month < 0) {
   240             y += month / 12;
   241             month = month % 12;
   242         }
   243         BaseCalendar cal = getCalendarSystem(y);
   244         cdate = (BaseCalendar.Datum) cal.newCalendarDate(TimeZone.getDefaultRef());
   245         cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs, min, sec, 0);
   246         getTimeImpl();
   247         cdate = null;
   248     }
   249 
   250     /**
   251      * Allocates a <code>Date</code> object and initializes it so that
   252      * it represents the date and time indicated by the string
   253      * <code>s</code>, which is interpreted as if by the
   254      * {@link Date#parse} method.
   255      *
   256      * @param   s   a string representation of the date.
   257      * @see     java.text.DateFormat
   258      * @see     java.util.Date#parse(java.lang.String)
   259      * @deprecated As of JDK version 1.1,
   260      * replaced by <code>DateFormat.parse(String s)</code>.
   261      */
   262     @Deprecated
   263     public Date(String s) {
   264         this(parse(s));
   265     }
   266 
   267     /**
   268      * Return a copy of this object.
   269      */
   270     public Object clone() {
   271         Date d = null;
   272         try {
   273             d = (Date)super.clone();
   274             if (cdate != null) {
   275                 d.cdate = (BaseCalendar.Datum) cdate.clone();
   276             }
   277         } catch (CloneNotSupportedException e) {} // Won't happen
   278         return d;
   279     }
   280 
   281     /**
   282      * Determines the date and time based on the arguments. The
   283      * arguments are interpreted as a year, month, day of the month,
   284      * hour of the day, minute within the hour, and second within the
   285      * minute, exactly as for the <tt>Date</tt> constructor with six
   286      * arguments, except that the arguments are interpreted relative
   287      * to UTC rather than to the local time zone. The time indicated is
   288      * returned represented as the distance, measured in milliseconds,
   289      * of that time from the epoch (00:00:00 GMT on January 1, 1970).
   290      *
   291      * @param   year    the year minus 1900.
   292      * @param   month   the month between 0-11.
   293      * @param   date    the day of the month between 1-31.
   294      * @param   hrs     the hours between 0-23.
   295      * @param   min     the minutes between 0-59.
   296      * @param   sec     the seconds between 0-59.
   297      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT for
   298      *          the date and time specified by the arguments.
   299      * @see     java.util.Calendar
   300      * @deprecated As of JDK version 1.1,
   301      * replaced by <code>Calendar.set(year + 1900, month, date,
   302      * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
   303      * month, date, hrs, min, sec)</code>, using a UTC
   304      * <code>TimeZone</code>, followed by <code>Calendar.getTime().getTime()</code>.
   305      */
   306     @Deprecated
   307     public static long UTC(int year, int month, int date,
   308                            int hrs, int min, int sec) {
   309         int y = year + 1900;
   310         // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
   311         if (month >= 12) {
   312             y += month / 12;
   313             month %= 12;
   314         } else if (month < 0) {
   315             y += month / 12;
   316             month = month % 12;
   317         }
   318         int m = month + 1;
   319         BaseCalendar cal = getCalendarSystem(y);
   320         BaseCalendar.Datum udate = (BaseCalendar.Datum) cal.newCalendarDate(null);
   321         udate.setNormalizedDate(y, m, date).setTimeOfDay(hrs, min, sec, 0);
   322 
   323         // Use a Date instance to perform normalization. Its fastTime
   324         // is the UTC value after the normalization.
   325         Date d = new Date(0);
   326         d.normalize(udate);
   327         return d.fastTime;
   328     }
   329 
   330     /**
   331      * Attempts to interpret the string <tt>s</tt> as a representation
   332      * of a date and time. If the attempt is successful, the time
   333      * indicated is returned represented as the distance, measured in
   334      * milliseconds, of that time from the epoch (00:00:00 GMT on
   335      * January 1, 1970). If the attempt fails, an
   336      * <tt>IllegalArgumentException</tt> is thrown.
   337      * <p>
   338      * It accepts many syntaxes; in particular, it recognizes the IETF
   339      * standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also
   340      * understands the continental U.S. time-zone abbreviations, but for
   341      * general use, a time-zone offset should be used: "Sat, 12 Aug 1995
   342      * 13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich
   343      * meridian). If no time zone is specified, the local time zone is
   344      * assumed. GMT and UTC are considered equivalent.
   345      * <p>
   346      * The string <tt>s</tt> is processed from left to right, looking for
   347      * data of interest. Any material in <tt>s</tt> that is within the
   348      * ASCII parenthesis characters <tt>(</tt> and <tt>)</tt> is ignored.
   349      * Parentheses may be nested. Otherwise, the only characters permitted
   350      * within <tt>s</tt> are these ASCII characters:
   351      * <blockquote><pre>
   352      * abcdefghijklmnopqrstuvwxyz
   353      * ABCDEFGHIJKLMNOPQRSTUVWXYZ
   354      * 0123456789,+-:/</pre></blockquote>
   355      * and whitespace characters.<p>
   356      * A consecutive sequence of decimal digits is treated as a decimal
   357      * number:<ul>
   358      * <li>If a number is preceded by <tt>+</tt> or <tt>-</tt> and a year
   359      *     has already been recognized, then the number is a time-zone
   360      *     offset. If the number is less than 24, it is an offset measured
   361      *     in hours. Otherwise, it is regarded as an offset in minutes,
   362      *     expressed in 24-hour time format without punctuation. A
   363      *     preceding <tt>-</tt> means a westward offset. Time zone offsets
   364      *     are always relative to UTC (Greenwich). Thus, for example,
   365      *     <tt>-5</tt> occurring in the string would mean "five hours west
   366      *     of Greenwich" and <tt>+0430</tt> would mean "four hours and
   367      *     thirty minutes east of Greenwich." It is permitted for the
   368      *     string to specify <tt>GMT</tt>, <tt>UT</tt>, or <tt>UTC</tt>
   369      *     redundantly-for example, <tt>GMT-5</tt> or <tt>utc+0430</tt>.
   370      * <li>The number is regarded as a year number if one of the
   371      *     following conditions is true:
   372      * <ul>
   373      *     <li>The number is equal to or greater than 70 and followed by a
   374      *         space, comma, slash, or end of string
   375      *     <li>The number is less than 70, and both a month and a day of
   376      *         the month have already been recognized</li>
   377      * </ul>
   378      *     If the recognized year number is less than 100, it is
   379      *     interpreted as an abbreviated year relative to a century of
   380      *     which dates are within 80 years before and 19 years after
   381      *     the time when the Date class is initialized.
   382      *     After adjusting the year number, 1900 is subtracted from
   383      *     it. For example, if the current year is 1999 then years in
   384      *     the range 19 to 99 are assumed to mean 1919 to 1999, while
   385      *     years from 0 to 18 are assumed to mean 2000 to 2018.  Note
   386      *     that this is slightly different from the interpretation of
   387      *     years less than 100 that is used in {@link java.text.SimpleDateFormat}.
   388      * <li>If the number is followed by a colon, it is regarded as an hour,
   389      *     unless an hour has already been recognized, in which case it is
   390      *     regarded as a minute.
   391      * <li>If the number is followed by a slash, it is regarded as a month
   392      *     (it is decreased by 1 to produce a number in the range <tt>0</tt>
   393      *     to <tt>11</tt>), unless a month has already been recognized, in
   394      *     which case it is regarded as a day of the month.
   395      * <li>If the number is followed by whitespace, a comma, a hyphen, or
   396      *     end of string, then if an hour has been recognized but not a
   397      *     minute, it is regarded as a minute; otherwise, if a minute has
   398      *     been recognized but not a second, it is regarded as a second;
   399      *     otherwise, it is regarded as a day of the month. </ul><p>
   400      * A consecutive sequence of letters is regarded as a word and treated
   401      * as follows:<ul>
   402      * <li>A word that matches <tt>AM</tt>, ignoring case, is ignored (but
   403      *     the parse fails if an hour has not been recognized or is less
   404      *     than <tt>1</tt> or greater than <tt>12</tt>).
   405      * <li>A word that matches <tt>PM</tt>, ignoring case, adds <tt>12</tt>
   406      *     to the hour (but the parse fails if an hour has not been
   407      *     recognized or is less than <tt>1</tt> or greater than <tt>12</tt>).
   408      * <li>Any word that matches any prefix of <tt>SUNDAY, MONDAY, TUESDAY,
   409      *     WEDNESDAY, THURSDAY, FRIDAY</tt>, or <tt>SATURDAY</tt>, ignoring
   410      *     case, is ignored. For example, <tt>sat, Friday, TUE</tt>, and
   411      *     <tt>Thurs</tt> are ignored.
   412      * <li>Otherwise, any word that matches any prefix of <tt>JANUARY,
   413      *     FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,
   414      *     OCTOBER, NOVEMBER</tt>, or <tt>DECEMBER</tt>, ignoring case, and
   415      *     considering them in the order given here, is recognized as
   416      *     specifying a month and is converted to a number (<tt>0</tt> to
   417      *     <tt>11</tt>). For example, <tt>aug, Sept, april</tt>, and
   418      *     <tt>NOV</tt> are recognized as months. So is <tt>Ma</tt>, which
   419      *     is recognized as <tt>MARCH</tt>, not <tt>MAY</tt>.
   420      * <li>Any word that matches <tt>GMT, UT</tt>, or <tt>UTC</tt>, ignoring
   421      *     case, is treated as referring to UTC.
   422      * <li>Any word that matches <tt>EST, CST, MST</tt>, or <tt>PST</tt>,
   423      *     ignoring case, is recognized as referring to the time zone in
   424      *     North America that is five, six, seven, or eight hours west of
   425      *     Greenwich, respectively. Any word that matches <tt>EDT, CDT,
   426      *     MDT</tt>, or <tt>PDT</tt>, ignoring case, is recognized as
   427      *     referring to the same time zone, respectively, during daylight
   428      *     saving time.</ul><p>
   429      * Once the entire string s has been scanned, it is converted to a time
   430      * result in one of two ways. If a time zone or time-zone offset has been
   431      * recognized, then the year, month, day of month, hour, minute, and
   432      * second are interpreted in UTC and then the time-zone offset is
   433      * applied. Otherwise, the year, month, day of month, hour, minute, and
   434      * second are interpreted in the local time zone.
   435      *
   436      * @param   s   a string to be parsed as a date.
   437      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
   438      *          represented by the string argument.
   439      * @see     java.text.DateFormat
   440      * @deprecated As of JDK version 1.1,
   441      * replaced by <code>DateFormat.parse(String s)</code>.
   442      */
   443     @Deprecated
   444     public static long parse(String s) {
   445         int year = Integer.MIN_VALUE;
   446         int mon = -1;
   447         int mday = -1;
   448         int hour = -1;
   449         int min = -1;
   450         int sec = -1;
   451         int millis = -1;
   452         int c = -1;
   453         int i = 0;
   454         int n = -1;
   455         int wst = -1;
   456         int tzoffset = -1;
   457         int prevc = 0;
   458     syntax:
   459         {
   460             if (s == null)
   461                 break syntax;
   462             int limit = s.length();
   463             while (i < limit) {
   464                 c = s.charAt(i);
   465                 i++;
   466                 if (c <= ' ' || c == ',')
   467                     continue;
   468                 if (c == '(') { // skip comments
   469                     int depth = 1;
   470                     while (i < limit) {
   471                         c = s.charAt(i);
   472                         i++;
   473                         if (c == '(') depth++;
   474                         else if (c == ')')
   475                             if (--depth <= 0)
   476                                 break;
   477                     }
   478                     continue;
   479                 }
   480                 if ('0' <= c && c <= '9') {
   481                     n = c - '0';
   482                     while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
   483                         n = n * 10 + c - '0';
   484                         i++;
   485                     }
   486                     if (prevc == '+' || prevc == '-' && year != Integer.MIN_VALUE) {
   487                         // timezone offset
   488                         if (n < 24)
   489                             n = n * 60; // EG. "GMT-3"
   490                         else
   491                             n = n % 100 + n / 100 * 60; // eg "GMT-0430"
   492                         if (prevc == '+')   // plus means east of GMT
   493                             n = -n;
   494                         if (tzoffset != 0 && tzoffset != -1)
   495                             break syntax;
   496                         tzoffset = n;
   497                     } else if (n >= 70)
   498                         if (year != Integer.MIN_VALUE)
   499                             break syntax;
   500                         else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
   501                             // year = n < 1900 ? n : n - 1900;
   502                             year = n;
   503                         else
   504                             break syntax;
   505                     else if (c == ':')
   506                         if (hour < 0)
   507                             hour = (byte) n;
   508                         else if (min < 0)
   509                             min = (byte) n;
   510                         else
   511                             break syntax;
   512                     else if (c == '/')
   513                         if (mon < 0)
   514                             mon = (byte) (n - 1);
   515                         else if (mday < 0)
   516                             mday = (byte) n;
   517                         else
   518                             break syntax;
   519                     else if (i < limit && c != ',' && c > ' ' && c != '-')
   520                         break syntax;
   521                     else if (hour >= 0 && min < 0)
   522                         min = (byte) n;
   523                     else if (min >= 0 && sec < 0)
   524                         sec = (byte) n;
   525                     else if (mday < 0)
   526                         mday = (byte) n;
   527                     // Handle two-digit years < 70 (70-99 handled above).
   528                     else if (year == Integer.MIN_VALUE && mon >= 0 && mday >= 0)
   529                         year = n;
   530                     else
   531                         break syntax;
   532                     prevc = 0;
   533                 } else if (c == '/' || c == ':' || c == '+' || c == '-')
   534                     prevc = c;
   535                 else {
   536                     int st = i - 1;
   537                     while (i < limit) {
   538                         c = s.charAt(i);
   539                         if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'))
   540                             break;
   541                         i++;
   542                     }
   543                     if (i <= st + 1)
   544                         break syntax;
   545                     int k;
   546                     for (k = wtb.length; --k >= 0;)
   547                         if (wtb[k].regionMatches(true, 0, s, st, i - st)) {
   548                             int action = ttb[k];
   549                             if (action != 0) {
   550                                 if (action == 1) {  // pm
   551                                     if (hour > 12 || hour < 1)
   552                                         break syntax;
   553                                     else if (hour < 12)
   554                                         hour += 12;
   555                                 } else if (action == 14) {  // am
   556                                     if (hour > 12 || hour < 1)
   557                                         break syntax;
   558                                     else if (hour == 12)
   559                                         hour = 0;
   560                                 } else if (action <= 13) {  // month!
   561                                     if (mon < 0)
   562                                         mon = (byte) (action - 2);
   563                                     else
   564                                         break syntax;
   565                                 } else {
   566                                     tzoffset = action - 10000;
   567                                 }
   568                             }
   569                             break;
   570                         }
   571                     if (k < 0)
   572                         break syntax;
   573                     prevc = 0;
   574                 }
   575             }
   576             if (year == Integer.MIN_VALUE || mon < 0 || mday < 0)
   577                 break syntax;
   578             // Parse 2-digit years within the correct default century.
   579             if (year < 100) {
   580                 synchronized (Date.class) {
   581                     if (defaultCenturyStart == 0) {
   582                         defaultCenturyStart = gcal.getCalendarDate().getYear() - 80;
   583                     }
   584                 }
   585                 year += (defaultCenturyStart / 100) * 100;
   586                 if (year < defaultCenturyStart) year += 100;
   587             }
   588             if (sec < 0)
   589                 sec = 0;
   590             if (min < 0)
   591                 min = 0;
   592             if (hour < 0)
   593                 hour = 0;
   594             BaseCalendar cal = getCalendarSystem(year);
   595             if (tzoffset == -1)  { // no time zone specified, have to use local
   596                 BaseCalendar.Datum ldate = (BaseCalendar.Datum) cal.newCalendarDate(TimeZone.getDefaultRef());
   597                 ldate.setDate(year, mon + 1, mday);
   598                 ldate.setTimeOfDay(hour, min, sec, 0);
   599                 return cal.getTime(ldate);
   600             }
   601             BaseCalendar.Datum udate = (BaseCalendar.Datum) cal.newCalendarDate(null); // no time zone
   602             udate.setDate(year, mon + 1, mday);
   603             udate.setTimeOfDay(hour, min, sec, 0);
   604             return cal.getTime(udate) + tzoffset * (60 * 1000);
   605         }
   606         // syntax error
   607         throw new IllegalArgumentException();
   608     }
   609     private final static String wtb[] = {
   610         "am", "pm",
   611         "monday", "tuesday", "wednesday", "thursday", "friday",
   612         "saturday", "sunday",
   613         "january", "february", "march", "april", "may", "june",
   614         "july", "august", "september", "october", "november", "december",
   615         "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
   616         "mst", "mdt", "pst", "pdt"
   617     };
   618     private final static int ttb[] = {
   619         14, 1, 0, 0, 0, 0, 0, 0, 0,
   620         2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
   621         10000 + 0, 10000 + 0, 10000 + 0,    // GMT/UT/UTC
   622         10000 + 5 * 60, 10000 + 4 * 60,     // EST/EDT
   623         10000 + 6 * 60, 10000 + 5 * 60,     // CST/CDT
   624         10000 + 7 * 60, 10000 + 6 * 60,     // MST/MDT
   625         10000 + 8 * 60, 10000 + 7 * 60      // PST/PDT
   626     };
   627 
   628     /**
   629      * Returns a value that is the result of subtracting 1900 from the
   630      * year that contains or begins with the instant in time represented
   631      * by this <code>Date</code> object, as interpreted in the local
   632      * time zone.
   633      *
   634      * @return  the year represented by this date, minus 1900.
   635      * @see     java.util.Calendar
   636      * @deprecated As of JDK version 1.1,
   637      * replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>.
   638      */
   639     @Deprecated
   640     public int getYear() {
   641         return normalize().getYear() - 1900;
   642     }
   643 
   644     /**
   645      * Sets the year of this <tt>Date</tt> object to be the specified
   646      * value plus 1900. This <code>Date</code> object is modified so
   647      * that it represents a point in time within the specified year,
   648      * with the month, date, hour, minute, and second the same as
   649      * before, as interpreted in the local time zone. (Of course, if
   650      * the date was February 29, for example, and the year is set to a
   651      * non-leap year, then the new date will be treated as if it were
   652      * on March 1.)
   653      *
   654      * @param   year    the year value.
   655      * @see     java.util.Calendar
   656      * @deprecated As of JDK version 1.1,
   657      * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>.
   658      */
   659     @Deprecated
   660     public void setYear(int year) {
   661         getCalendarDate().setNormalizedYear(year + 1900);
   662     }
   663 
   664     /**
   665      * Returns a number representing the month that contains or begins
   666      * with the instant in time represented by this <tt>Date</tt> object.
   667      * The value returned is between <code>0</code> and <code>11</code>,
   668      * with the value <code>0</code> representing January.
   669      *
   670      * @return  the month represented by this date.
   671      * @see     java.util.Calendar
   672      * @deprecated As of JDK version 1.1,
   673      * replaced by <code>Calendar.get(Calendar.MONTH)</code>.
   674      */
   675     @Deprecated
   676     public int getMonth() {
   677         return normalize().getMonth() - 1; // adjust 1-based to 0-based
   678     }
   679 
   680     /**
   681      * Sets the month of this date to the specified value. This
   682      * <tt>Date</tt> object is modified so that it represents a point
   683      * in time within the specified month, with the year, date, hour,
   684      * minute, and second the same as before, as interpreted in the
   685      * local time zone. If the date was October 31, for example, and
   686      * the month is set to June, then the new date will be treated as
   687      * if it were on July 1, because June has only 30 days.
   688      *
   689      * @param   month   the month value between 0-11.
   690      * @see     java.util.Calendar
   691      * @deprecated As of JDK version 1.1,
   692      * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>.
   693      */
   694     @Deprecated
   695     public void setMonth(int month) {
   696         int y = 0;
   697         if (month >= 12) {
   698             y = month / 12;
   699             month %= 12;
   700         } else if (month < 0) {
   701             y = month / 12;
   702             month = month % 12;
   703         }
   704         BaseCalendar.Datum d = getCalendarDate();
   705         if (y != 0) {
   706             d.setNormalizedYear(d.getNormalizedYear() + y);
   707         }
   708         d.setMonth(month + 1); // adjust 0-based to 1-based month numbering
   709     }
   710 
   711     /**
   712      * Returns the day of the month represented by this <tt>Date</tt> object.
   713      * The value returned is between <code>1</code> and <code>31</code>
   714      * representing the day of the month that contains or begins with the
   715      * instant in time represented by this <tt>Date</tt> object, as
   716      * interpreted in the local time zone.
   717      *
   718      * @return  the day of the month represented by this date.
   719      * @see     java.util.Calendar
   720      * @deprecated As of JDK version 1.1,
   721      * replaced by <code>Calendar.get(Calendar.DAY_OF_MONTH)</code>.
   722      * @deprecated
   723      */
   724     @Deprecated
   725     public int getDate() {
   726         return normalize().getDayOfMonth();
   727     }
   728 
   729     /**
   730      * Sets the day of the month of this <tt>Date</tt> object to the
   731      * specified value. This <tt>Date</tt> object is modified so that
   732      * it represents a point in time within the specified day of the
   733      * month, with the year, month, hour, minute, and second the same
   734      * as before, as interpreted in the local time zone. If the date
   735      * was April 30, for example, and the date is set to 31, then it
   736      * will be treated as if it were on May 1, because April has only
   737      * 30 days.
   738      *
   739      * @param   date   the day of the month value between 1-31.
   740      * @see     java.util.Calendar
   741      * @deprecated As of JDK version 1.1,
   742      * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>.
   743      */
   744     @Deprecated
   745     public void setDate(int date) {
   746         getCalendarDate().setDayOfMonth(date);
   747     }
   748 
   749     /**
   750      * Returns the day of the week represented by this date. The
   751      * returned value (<tt>0</tt> = Sunday, <tt>1</tt> = Monday,
   752      * <tt>2</tt> = Tuesday, <tt>3</tt> = Wednesday, <tt>4</tt> =
   753      * Thursday, <tt>5</tt> = Friday, <tt>6</tt> = Saturday)
   754      * represents the day of the week that contains or begins with
   755      * the instant in time represented by this <tt>Date</tt> object,
   756      * as interpreted in the local time zone.
   757      *
   758      * @return  the day of the week represented by this date.
   759      * @see     java.util.Calendar
   760      * @deprecated As of JDK version 1.1,
   761      * replaced by <code>Calendar.get(Calendar.DAY_OF_WEEK)</code>.
   762      */
   763     @Deprecated
   764     public int getDay() {
   765         return normalize().getDayOfWeek() - 7;//gcal.SUNDAY;
   766     }
   767 
   768     /**
   769      * Returns the hour represented by this <tt>Date</tt> object. The
   770      * returned value is a number (<tt>0</tt> through <tt>23</tt>)
   771      * representing the hour within the day that contains or begins
   772      * with the instant in time represented by this <tt>Date</tt>
   773      * object, as interpreted in the local time zone.
   774      *
   775      * @return  the hour represented by this date.
   776      * @see     java.util.Calendar
   777      * @deprecated As of JDK version 1.1,
   778      * replaced by <code>Calendar.get(Calendar.HOUR_OF_DAY)</code>.
   779      */
   780     @Deprecated
   781     public int getHours() {
   782         return normalize().getHours();
   783     }
   784 
   785     /**
   786      * Sets the hour of this <tt>Date</tt> object to the specified value.
   787      * This <tt>Date</tt> object is modified so that it represents a point
   788      * in time within the specified hour of the day, with the year, month,
   789      * date, minute, and second the same as before, as interpreted in the
   790      * local time zone.
   791      *
   792      * @param   hours   the hour value.
   793      * @see     java.util.Calendar
   794      * @deprecated As of JDK version 1.1,
   795      * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>.
   796      */
   797     @Deprecated
   798     public void setHours(int hours) {
   799         getCalendarDate().setHours(hours);
   800     }
   801 
   802     /**
   803      * Returns the number of minutes past the hour represented by this date,
   804      * as interpreted in the local time zone.
   805      * The value returned is between <code>0</code> and <code>59</code>.
   806      *
   807      * @return  the number of minutes past the hour represented by this date.
   808      * @see     java.util.Calendar
   809      * @deprecated As of JDK version 1.1,
   810      * replaced by <code>Calendar.get(Calendar.MINUTE)</code>.
   811      */
   812     @Deprecated
   813     public int getMinutes() {
   814         return normalize().getMinutes();
   815     }
   816 
   817     /**
   818      * Sets the minutes of this <tt>Date</tt> object to the specified value.
   819      * This <tt>Date</tt> object is modified so that it represents a point
   820      * in time within the specified minute of the hour, with the year, month,
   821      * date, hour, and second the same as before, as interpreted in the
   822      * local time zone.
   823      *
   824      * @param   minutes   the value of the minutes.
   825      * @see     java.util.Calendar
   826      * @deprecated As of JDK version 1.1,
   827      * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>.
   828      */
   829     @Deprecated
   830     public void setMinutes(int minutes) {
   831         getCalendarDate().setMinutes(minutes);
   832     }
   833 
   834     /**
   835      * Returns the number of seconds past the minute represented by this date.
   836      * The value returned is between <code>0</code> and <code>61</code>. The
   837      * values <code>60</code> and <code>61</code> can only occur on those
   838      * Java Virtual Machines that take leap seconds into account.
   839      *
   840      * @return  the number of seconds past the minute represented by this date.
   841      * @see     java.util.Calendar
   842      * @deprecated As of JDK version 1.1,
   843      * replaced by <code>Calendar.get(Calendar.SECOND)</code>.
   844      */
   845     @Deprecated
   846     public int getSeconds() {
   847         return normalize().getSeconds();
   848     }
   849 
   850     /**
   851      * Sets the seconds of this <tt>Date</tt> to the specified value.
   852      * This <tt>Date</tt> object is modified so that it represents a
   853      * point in time within the specified second of the minute, with
   854      * the year, month, date, hour, and minute the same as before, as
   855      * interpreted in the local time zone.
   856      *
   857      * @param   seconds   the seconds value.
   858      * @see     java.util.Calendar
   859      * @deprecated As of JDK version 1.1,
   860      * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>.
   861      */
   862     @Deprecated
   863     public void setSeconds(int seconds) {
   864         getCalendarDate().setSeconds(seconds);
   865     }
   866 
   867     /**
   868      * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
   869      * represented by this <tt>Date</tt> object.
   870      *
   871      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
   872      *          represented by this date.
   873      */
   874     public long getTime() {
   875         return getTimeImpl();
   876     }
   877 
   878     private final long getTimeImpl() {
   879         if (cdate != null && !cdate.isNormalized()) {
   880             normalize();
   881         }
   882         return fastTime;
   883     }
   884 
   885     /**
   886      * Sets this <code>Date</code> object to represent a point in time that is
   887      * <code>time</code> milliseconds after January 1, 1970 00:00:00 GMT.
   888      *
   889      * @param   time   the number of milliseconds.
   890      */
   891     public void setTime(long time) {
   892         fastTime = time;
   893         cdate = null;
   894     }
   895 
   896     /**
   897      * Tests if this date is before the specified date.
   898      *
   899      * @param   when   a date.
   900      * @return  <code>true</code> if and only if the instant of time
   901      *            represented by this <tt>Date</tt> object is strictly
   902      *            earlier than the instant represented by <tt>when</tt>;
   903      *          <code>false</code> otherwise.
   904      * @exception NullPointerException if <code>when</code> is null.
   905      */
   906     public boolean before(Date when) {
   907         return getMillisOf(this) < getMillisOf(when);
   908     }
   909 
   910     /**
   911      * Tests if this date is after the specified date.
   912      *
   913      * @param   when   a date.
   914      * @return  <code>true</code> if and only if the instant represented
   915      *          by this <tt>Date</tt> object is strictly later than the
   916      *          instant represented by <tt>when</tt>;
   917      *          <code>false</code> otherwise.
   918      * @exception NullPointerException if <code>when</code> is null.
   919      */
   920     public boolean after(Date when) {
   921         return getMillisOf(this) > getMillisOf(when);
   922     }
   923 
   924     /**
   925      * Compares two dates for equality.
   926      * The result is <code>true</code> if and only if the argument is
   927      * not <code>null</code> and is a <code>Date</code> object that
   928      * represents the same point in time, to the millisecond, as this object.
   929      * <p>
   930      * Thus, two <code>Date</code> objects are equal if and only if the
   931      * <code>getTime</code> method returns the same <code>long</code>
   932      * value for both.
   933      *
   934      * @param   obj   the object to compare with.
   935      * @return  <code>true</code> if the objects are the same;
   936      *          <code>false</code> otherwise.
   937      * @see     java.util.Date#getTime()
   938      */
   939     public boolean equals(Object obj) {
   940         return obj instanceof Date && getTime() == ((Date) obj).getTime();
   941     }
   942 
   943     /**
   944      * Returns the millisecond value of this <code>Date</code> object
   945      * without affecting its internal state.
   946      */
   947     static final long getMillisOf(Date date) {
   948         if (date.cdate == null || date.cdate.isNormalized()) {
   949             return date.fastTime;
   950         }
   951         BaseCalendar.Datum d = (BaseCalendar.Datum) date.cdate.clone();
   952         return gcal.getTime(d);
   953     }
   954 
   955     /**
   956      * Compares two Dates for ordering.
   957      *
   958      * @param   anotherDate   the <code>Date</code> to be compared.
   959      * @return  the value <code>0</code> if the argument Date is equal to
   960      *          this Date; a value less than <code>0</code> if this Date
   961      *          is before the Date argument; and a value greater than
   962      *      <code>0</code> if this Date is after the Date argument.
   963      * @since   1.2
   964      * @exception NullPointerException if <code>anotherDate</code> is null.
   965      */
   966     public int compareTo(Date anotherDate) {
   967         long thisTime = getMillisOf(this);
   968         long anotherTime = getMillisOf(anotherDate);
   969         return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
   970     }
   971 
   972     /**
   973      * Returns a hash code value for this object. The result is the
   974      * exclusive OR of the two halves of the primitive <tt>long</tt>
   975      * value returned by the {@link Date#getTime}
   976      * method. That is, the hash code is the value of the expression:
   977      * <blockquote><pre>
   978      * (int)(this.getTime()^(this.getTime() >>> 32))</pre></blockquote>
   979      *
   980      * @return  a hash code value for this object.
   981      */
   982     public int hashCode() {
   983         long ht = this.getTime();
   984         return (int) ht ^ (int) (ht >> 32);
   985     }
   986 
   987     /**
   988      * Converts this <code>Date</code> object to a <code>String</code>
   989      * of the form:
   990      * <blockquote><pre>
   991      * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
   992      * where:<ul>
   993      * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed,
   994      *     Thu, Fri, Sat</tt>).
   995      * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun,
   996      *     Jul, Aug, Sep, Oct, Nov, Dec</tt>).
   997      * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through
   998      *     <tt>31</tt>), as two decimal digits.
   999      * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through
  1000      *     <tt>23</tt>), as two decimal digits.
  1001      * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through
  1002      *     <tt>59</tt>), as two decimal digits.
  1003      * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through
  1004      *     <tt>61</tt>, as two decimal digits.
  1005      * <li><tt>zzz</tt> is the time zone (and may reflect daylight saving
  1006      *     time). Standard time zone abbreviations include those
  1007      *     recognized by the method <tt>parse</tt>. If time zone
  1008      *     information is not available, then <tt>zzz</tt> is empty -
  1009      *     that is, it consists of no characters at all.
  1010      * <li><tt>yyyy</tt> is the year, as four decimal digits.
  1011      * </ul>
  1012      *
  1013      * @return  a string representation of this date.
  1014      * @see     java.util.Date#toLocaleString()
  1015      * @see     java.util.Date#toGMTString()
  1016      */
  1017     public String toString() {
  1018         // "EEE MMM dd HH:mm:ss zzz yyyy";
  1019         BaseCalendar.Datum date = normalize();
  1020         StringBuilder sb = new StringBuilder(28);
  1021         int index = date.getDayOfWeek();
  1022         if (index == 7) {
  1023             index = 8;
  1024         }
  1025         convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
  1026         convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
  1027 //        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
  1028 //
  1029 //        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
  1030 //        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
  1031 //        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
  1032 //        TimeZone zi = date.getZone();
  1033 //        if (zi != null) {
  1034 //            sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz
  1035 //        } else {
  1036 //            sb.append("GMT");
  1037 //        }
  1038         sb.append(' ').append(date.getYear());  // yyyy
  1039         return sb.toString();
  1040     }
  1041 
  1042     /**
  1043      * Converts the given name to its 3-letter abbreviation (e.g.,
  1044      * "monday" -> "Mon") and stored the abbreviation in the given
  1045      * <code>StringBuilder</code>.
  1046      */
  1047     private static final StringBuilder convertToAbbr(StringBuilder sb, String name) {
  1048         sb.append(Character.toUpperCase(name.charAt(0)));
  1049         sb.append(name.charAt(1)).append(name.charAt(2));
  1050         return sb;
  1051     }
  1052 
  1053     /**
  1054      * Creates a string representation of this <tt>Date</tt> object in an
  1055      * implementation-dependent form. The intent is that the form should
  1056      * be familiar to the user of the Java application, wherever it may
  1057      * happen to be running. The intent is comparable to that of the
  1058      * "<code>%c</code>" format supported by the <code>strftime()</code>
  1059      * function of ISO&nbsp;C.
  1060      *
  1061      * @return  a string representation of this date, using the locale
  1062      *          conventions.
  1063      * @see     java.text.DateFormat
  1064      * @see     java.util.Date#toString()
  1065      * @see     java.util.Date#toGMTString()
  1066      * @deprecated As of JDK version 1.1,
  1067      * replaced by <code>DateFormat.format(Date date)</code>.
  1068      */
  1069     @Deprecated
  1070     public String toLocaleString() {
  1071         DateFormat formatter = DateFormat.getDateTimeInstance();
  1072         return formatter.format(this);
  1073     }
  1074 
  1075     /**
  1076      * Creates a string representation of this <tt>Date</tt> object of
  1077      * the form:
  1078      * <blockquote<pre>
  1079      * d mon yyyy hh:mm:ss GMT</pre></blockquote>
  1080      * where:<ul>
  1081      * <li><i>d</i> is the day of the month (<tt>1</tt> through <tt>31</tt>),
  1082      *     as one or two decimal digits.
  1083      * <li><i>mon</i> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, Jul,
  1084      *     Aug, Sep, Oct, Nov, Dec</tt>).
  1085      * <li><i>yyyy</i> is the year, as four decimal digits.
  1086      * <li><i>hh</i> is the hour of the day (<tt>00</tt> through <tt>23</tt>),
  1087      *     as two decimal digits.
  1088      * <li><i>mm</i> is the minute within the hour (<tt>00</tt> through
  1089      *     <tt>59</tt>), as two decimal digits.
  1090      * <li><i>ss</i> is the second within the minute (<tt>00</tt> through
  1091      *     <tt>61</tt>), as two decimal digits.
  1092      * <li><i>GMT</i> is exactly the ASCII letters "<tt>GMT</tt>" to indicate
  1093      *     Greenwich Mean Time.
  1094      * </ul><p>
  1095      * The result does not depend on the local time zone.
  1096      *
  1097      * @return  a string representation of this date, using the Internet GMT
  1098      *          conventions.
  1099      * @see     java.text.DateFormat
  1100      * @see     java.util.Date#toString()
  1101      * @see     java.util.Date#toLocaleString()
  1102      * @deprecated As of JDK version 1.1,
  1103      * replaced by <code>DateFormat.format(Date date)</code>, using a
  1104      * GMT <code>TimeZone</code>.
  1105      */
  1106     @Deprecated
  1107     public String toGMTString() {
  1108         // d MMM yyyy HH:mm:ss 'GMT'
  1109         long t = getTime();
  1110         BaseCalendar cal = getCalendarSystem(t);
  1111         StringBuilder sb = new StringBuilder(32);
  1112 //        BaseCalendar.Datum date =
  1113 //            (BaseCalendar.Datum) cal.getCalendarDate(getTime(), (TimeZone)null);
  1114 //        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 1).append(' '); // d
  1115 //        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
  1116 //        sb.append(date.getYear()).append(' ');                            // yyyy
  1117 //        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');      // HH
  1118 //        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':');    // mm
  1119 //        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2);                // ss
  1120         sb.append(" GMT");                                                // ' GMT'
  1121         return sb.toString();
  1122     }
  1123 
  1124     /**
  1125      * Returns the offset, measured in minutes, for the local time zone
  1126      * relative to UTC that is appropriate for the time represented by
  1127      * this <code>Date</code> object.
  1128      * <p>
  1129      * For example, in Massachusetts, five time zones west of Greenwich:
  1130      * <blockquote><pre>
  1131      * new Date(96, 1, 14).getTimezoneOffset() returns 300</pre></blockquote>
  1132      * because on February 14, 1996, standard time (Eastern Standard Time)
  1133      * is in use, which is offset five hours from UTC; but:
  1134      * <blockquote><pre>
  1135      * new Date(96, 5, 1).getTimezoneOffset() returns 240</pre></blockquote>
  1136      * because on June 1, 1996, daylight saving time (Eastern Daylight Time)
  1137      * is in use, which is offset only four hours from UTC.<p>
  1138      * This method produces the same result as if it computed:
  1139      * <blockquote><pre>
  1140      * (this.getTime() - UTC(this.getYear(),
  1141      *                       this.getMonth(),
  1142      *                       this.getDate(),
  1143      *                       this.getHours(),
  1144      *                       this.getMinutes(),
  1145      *                       this.getSeconds())) / (60 * 1000)
  1146      * </pre></blockquote>
  1147      *
  1148      * @return  the time-zone offset, in minutes, for the current time zone.
  1149      * @see     java.util.Calendar#ZONE_OFFSET
  1150      * @see     java.util.Calendar#DST_OFFSET
  1151      * @see     java.util.TimeZone#getDefault
  1152      * @deprecated As of JDK version 1.1,
  1153      * replaced by <code>-(Calendar.get(Calendar.ZONE_OFFSET) +
  1154      * Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)</code>.
  1155      */
  1156     @Deprecated
  1157     public int getTimezoneOffset() {
  1158         int zoneOffset;
  1159         if (cdate == null) {
  1160             TimeZone tz = TimeZone.getDefaultRef();
  1161             zoneOffset = tz.getOffset(fastTime);
  1162         } else {
  1163             normalize();
  1164             zoneOffset = cdate.getZoneOffset();
  1165         }
  1166         return -zoneOffset/60000;  // convert to minutes
  1167     }
  1168 
  1169     private final BaseCalendar.Datum getCalendarDate() {
  1170         if (cdate == null) {
  1171 //            BaseCalendar cal = getCalendarSystem(fastTime);
  1172 //            cdate = (BaseCalendar.Datum) cal.getCalendarDate(fastTime,
  1173 //                                                            TimeZone.getDefaultRef());
  1174         }
  1175         return cdate;
  1176     }
  1177 
  1178     private final BaseCalendar.Datum normalize() {
  1179         if (cdate == null) {
  1180 //            BaseCalendar cal = getCalendarSystem(fastTime);
  1181 //            cdate = (BaseCalendar.Datum) cal.getCalendarDate(fastTime,
  1182 //                                                            TimeZone.getDefaultRef());
  1183 //            return cdate;
  1184         }
  1185 
  1186         // Normalize cdate with the TimeZone in cdate first. This is
  1187         // required for the compatible behavior.
  1188         if (!cdate.isNormalized()) {
  1189             cdate = normalize(cdate);
  1190         }
  1191 
  1192         // If the default TimeZone has changed, then recalculate the
  1193         // fields with the new TimeZone.
  1194         TimeZone tz = TimeZone.getDefaultRef();
  1195         if (tz != cdate.getZone()) {
  1196 //            cdate.setZone(tz);
  1197 //            CalendarSystem cal = getCalendarSystem(cdate);
  1198 //            cal.getCalendarDate(fastTime, cdate);
  1199         }
  1200         return cdate;
  1201     }
  1202 
  1203     // fastTime and the returned data are in sync upon return.
  1204     private final BaseCalendar.Datum normalize(BaseCalendar.Datum date) {
  1205         int y = date.getNormalizedYear();
  1206         int m = date.getMonth();
  1207         int d = date.getDayOfMonth();
  1208         int hh = date.getHours();
  1209         int mm = date.getMinutes();
  1210         int ss = date.getSeconds();
  1211         int ms = date.getMillis();
  1212         TimeZone tz = date.getZone();
  1213 
  1214         // If the specified year can't be handled using a long value
  1215         // in milliseconds, GregorianCalendar is used for full
  1216         // compatibility with underflow and overflow. This is required
  1217         // by some JCK tests. The limits are based max year values -
  1218         // years that can be represented by max values of d, hh, mm,
  1219         // ss and ms. Also, let GregorianCalendar handle the default
  1220         // cutover year so that we don't need to worry about the
  1221         // transition here.
  1222 //        if (y == 1582 || y > 280000000 || y < -280000000) {
  1223 //            if (tz == null) {
  1224 //                tz = TimeZone.getTimeZone("GMT");
  1225 //            }
  1226 //            GregorianCalendar gc = new GregorianCalendar(tz);
  1227 //            gc.clear();
  1228 //            gc.set(gc.MILLISECOND, ms);
  1229 //            gc.set(y, m-1, d, hh, mm, ss);
  1230 //            fastTime = gc.getTimeInMillis();
  1231 //            BaseCalendar cal = getCalendarSystem(fastTime);
  1232 //            date = (BaseCalendar.Datum) cal.getCalendarDate(fastTime, tz);
  1233 //            return date;
  1234 //        }
  1235 
  1236         BaseCalendar cal = getCalendarSystem(y);
  1237         if (cal != getCalendarSystem(date)) {
  1238             date = (BaseCalendar.Datum) cal.newCalendarDate(tz);
  1239             date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
  1240         }
  1241         // Perform the GregorianCalendar-style normalization.
  1242         fastTime = cal.getTime(date);
  1243 
  1244         // In case the normalized date requires the other calendar
  1245         // system, we need to recalculate it using the other one.
  1246         BaseCalendar ncal = getCalendarSystem(fastTime);
  1247         if (ncal != cal) {
  1248             date = (BaseCalendar.Datum) ncal.newCalendarDate(tz);
  1249             date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
  1250             fastTime = ncal.getTime(date);
  1251         }
  1252         return date;
  1253     }
  1254 
  1255     /**
  1256      * Returns the Gregorian or Julian calendar system to use with the
  1257      * given date. Use Gregorian from October 15, 1582.
  1258      *
  1259      * @param year normalized calendar year (not -1900)
  1260      * @return the CalendarSystem to use for the specified date
  1261      */
  1262     private static final BaseCalendar getCalendarSystem(int year) {
  1263         if (year >= 1582) {
  1264             return gcal;
  1265         }
  1266         return getJulianCalendar();
  1267     }
  1268 
  1269     private static final BaseCalendar getCalendarSystem(long utc) {
  1270         // Quickly check if the time stamp given by `utc' is the Epoch
  1271         // or later. If it's before 1970, we convert the cutover to
  1272         // local time to compare.
  1273 //        if (utc >= 0
  1274 //            || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER
  1275 //                        - TimeZone.getDefaultRef().getOffset(utc)) {
  1276             return gcal;
  1277 //        }
  1278 //        return getJulianCalendar();
  1279     }
  1280 
  1281     private static final BaseCalendar getCalendarSystem(BaseCalendar.Datum cdate) {
  1282         if (jcal == null) {
  1283             return gcal;
  1284         }
  1285         if (cdate.getEra() != null) {
  1286             return jcal;
  1287         }
  1288         return gcal;
  1289     }
  1290 
  1291     synchronized private static final BaseCalendar getJulianCalendar() {
  1292         if (jcal == null) {
  1293 //            jcal = (BaseCalendar) CalendarSystem.forName("julian");
  1294         }
  1295         return jcal;
  1296     }
  1297 
  1298     /**
  1299      * Save the state of this object to a stream (i.e., serialize it).
  1300      *
  1301      * @serialData The value returned by <code>getTime()</code>
  1302      *             is emitted (long).  This represents the offset from
  1303      *             January 1, 1970, 00:00:00 GMT in milliseconds.
  1304      */
  1305     private void writeObject(ObjectOutputStream s)
  1306          throws IOException
  1307     {
  1308         s.writeLong(getTimeImpl());
  1309     }
  1310 
  1311     /**
  1312      * Reconstitute this object from a stream (i.e., deserialize it).
  1313      */
  1314     private void readObject(ObjectInputStream s)
  1315          throws IOException, ClassNotFoundException
  1316     {
  1317         fastTime = s.readLong();
  1318     }
  1319     
  1320     static final class BaseCalendar {
  1321         Datum newCalendarDate(TimeZone t) {
  1322             return new Datum();
  1323         }
  1324         
  1325         Datum getNthDayOfWeek(int a, int b, Datum c) {
  1326             return new Datum();
  1327         }
  1328 
  1329         Datum getCalendarDate() {
  1330             return new Datum();
  1331         }
  1332 
  1333         int getTime(Datum udate) {
  1334             return 0;
  1335         }
  1336 
  1337         int getMonthLength(Datum cdate) {
  1338             return 0;
  1339         }
  1340 
  1341         void getCalendarDate(long l, Datum cdate) {
  1342         }
  1343         
  1344         static class Datum implements Cloneable {
  1345             public Datum clone() {
  1346                 return new Datum();
  1347             }
  1348             
  1349             Datum setNormalizedDate(int y, int i, int date) {
  1350                 return this;
  1351             }
  1352 
  1353             void setTimeOfDay(int hrs, int min, int sec, int i) {
  1354             }
  1355 
  1356             int getYear() {
  1357                 return 0;
  1358             }
  1359 
  1360             void setDate(int year, int i, int mday) {
  1361             }
  1362 
  1363             void setNormalizedYear(int i) {
  1364             }
  1365 
  1366             int getMonth() {
  1367                 return 0;
  1368             }
  1369 
  1370             int getNormalizedYear() {
  1371                 return 0;
  1372             }
  1373 
  1374             void setMonth(int i) {
  1375             }
  1376 
  1377             int getDayOfMonth() {
  1378                 return 0;
  1379             }
  1380 
  1381             void setDayOfMonth(int date) {
  1382             }
  1383 
  1384             int getDayOfWeek() {
  1385                 return 0;
  1386             }
  1387 
  1388             int getHours() {
  1389                 return 0;
  1390             }
  1391 
  1392             void setHours(int hours) {
  1393             }
  1394 
  1395             int getMinutes() {
  1396                 return 0;
  1397             }
  1398 
  1399             void setMinutes(int minutes) {
  1400             }
  1401 
  1402             int getSeconds() {
  1403                 return 0;
  1404             }
  1405 
  1406             void setSeconds(int seconds) {
  1407             }
  1408 
  1409             boolean isNormalized() {
  1410                 return false;
  1411             }
  1412 
  1413             Object getEra() {
  1414                 return this;
  1415             }
  1416 
  1417             int getMillis() {
  1418                 return 0;
  1419             }
  1420 
  1421             TimeZone getZone() {
  1422                 return TimeZone.NO_TIMEZONE;
  1423             }
  1424 
  1425             int getZoneOffset() {
  1426                 return 0;
  1427             }
  1428         }
  1429     }
  1430 }