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