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