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
26package java.util;
27
28import java.text.DateFormat;
29import java.time.LocalDate;
30import java.io.IOException;
31import java.io.ObjectOutputStream;
32import java.io.ObjectInputStream;
33import java.lang.ref.SoftReference;
34import java.time.Instant;
35import sun.util.calendar.BaseCalendar;
36import sun.util.calendar.CalendarDate;
37import sun.util.calendar.CalendarSystem;
38import sun.util.calendar.CalendarUtils;
39import sun.util.calendar.Era;
40import sun.util.calendar.Gregorian;
41import 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 */
133public 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}
1380