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