1 /*
2  * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */

25
26 package java.util;
27
28 import java.text.DateFormat;
29 import java.time.LocalDate;
30 import java.io.IOException;
31 import java.io.ObjectOutputStream;
32 import java.io.ObjectInputStream;
33 import java.lang.ref.SoftReference;
34 import java.time.Instant;
35 import sun.util.calendar.BaseCalendar;
36 import sun.util.calendar.CalendarDate;
37 import sun.util.calendar.CalendarSystem;
38 import sun.util.calendar.CalendarUtils;
39 import sun.util.calendar.Era;
40 import sun.util.calendar.Gregorian;
41 import sun.util.calendar.ZoneInfo;
42
43 /**
44  * The class {@code Date} represents a specific instant
45  * in time, with millisecond precision.
46  * <p>
47  * Prior to JDK&nbsp;1.1, the class {@code Date} had two additional
48  * functions.  It allowed the interpretation of dates as year, month, day, hour,
49  * minute, and second values.  It also allowed the formatting and parsing
50  * of date strings.  Unfortunately, the API for these functions was not
51  * amenable to internationalization.  As of JDK&nbsp;1.1, the
52  * {@code Calendar} class should be used to convert between dates and time
53  * fields and the {@code DateFormat} class should be used to format and
54  * parse date strings.
55  * The corresponding methods in {@code Date} are deprecated.
56  * <p>
57  * Although the {@code Date} class is intended to reflect
58  * coordinated universal time (UTC), it may not do so exactly,
59  * depending on the host environment of the Java Virtual Machine.
60  * Nearly all modern operating systems assume that 1&nbsp;day&nbsp;=
61  * 24&nbsp;&times;&nbsp;60&nbsp;&times;&nbsp;60&nbsp;= 86400 seconds
62  * in all cases. In UTC, however, about once every year or two there
63  * is an extra second, called a "leap second." The leap
64  * second is always added as the last second of the day, and always
65  * on December 31 or June 30. For example, the last minute of the
66  * year 1995 was 61 seconds long, thanks to an added leap second.
67  * Most computer clocks are not accurate enough to be able to reflect
68  * the leap-second distinction.
69  * <p>
70  * Some computer standards are defined in terms of Greenwich mean
71  * time (GMT), which is equivalent to universal time (UT).  GMT is
72  * the "civil" name for the standard; UT is the
73  * "scientific" name for the same standard. The
74  * distinction between UTC and UT is that UTC is based on an atomic
75  * clock and UT is based on astronomical observations, which for all
76  * practical purposes is an invisibly fine hair to split. Because the
77  * earth's rotation is not uniform (it slows down and speeds up
78  * in complicated ways), UT does not always flow uniformly. Leap
79  * seconds are introduced as needed into UTC so as to keep UTC within
80  * 0.9 seconds of UT1, which is a version of UT with certain
81  * corrections applied. There are other time and date systems as
82  * well; for example, the time scale used by the satellite-based
83  * global positioning system (GPS) is synchronized to UTC but is
84  * <i>not</i> adjusted for leap seconds. An interesting source of
85  * further information is the United States Naval Observatory (USNO):
86  * <blockquote><pre>
87  *     <a href="http://www.usno.navy.mil/USNO">http://www.usno.navy.mil/USNO</a>
88  * </pre></blockquote>
89  * <p>
90  * and the material regarding "Systems of Time" at:
91  * <blockquote><pre>
92  *     <a href="http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time">http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time</a>
93  * </pre></blockquote>
94  * <p>
95  * which has descriptions of various different time systems including
96  * UT, UT1, and UTC.
97  * <p>
98  * In all methods of class {@code Date} that accept or return
99  * year, month, date, hours, minutes, and seconds values, the
100  * following representations are used:
101  * <ul>
102  * <li>A year <i>y</i> is represented by the integer
103  *     <i>y</i>&nbsp;{@code - 1900}.
104  * <li>A month is represented by an integer from 0 to 11; 0 is January,
105  *     1 is February, and so forth; thus 11 is December.
106  * <li>A date (day of month) is represented by an integer from 1 to 31
107  *     in the usual manner.
108  * <li>An hour is represented by an integer from 0 to 23. Thus, the hour
109  *     from midnight to 1 a.m. is hour 0, and the hour from noon to 1
110  *     p.m. is hour 12.
111  * <li>A minute is represented by an integer from 0 to 59 in the usual manner.
112  * <li>A second is represented by an integer from 0 to 61; the values 60 and
113  *     61 occur only for leap seconds and even then only in Java
114  *     implementations that actually track leap seconds correctly. Because
115  *     of the manner in which leap seconds are currently introduced, it is
116  *     extremely unlikely that two leap seconds will occur in the same
117  *     minute, but this specification follows the date and time conventions
118  *     for ISO C.
119  * </ul>
120  * <p>
121  * In all cases, arguments given to methods for these purposes need
122  * not fall within the indicated ranges; for example, a date may be
123  * specified as January 32 and is interpreted as meaning February 1.
124  *
125  * @author  James Gosling
126  * @author  Arthur van Hoff
127  * @author  Alan Liu
128  * @see     java.text.DateFormat
129  * @see     java.util.Calendar
130  * @see     java.util.TimeZone
131  * @since   1.0
132  */

133 public class Date
134     implements java.io.Serializable, Cloneable, Comparable<Date>
135 {
136     private static final BaseCalendar gcal =
137                                 CalendarSystem.getGregorianCalendar();
138     private static BaseCalendar jcal;
139
140     private transient long fastTime;
141
142     /*
143      * If cdate is null, then fastTime indicates the time in millis.
144      * If cdate.isNormalized() is true, then fastTime and cdate are in
145      * synch. Otherwise, fastTime is ignored, and cdate indicates the
146      * time.
147      */

148     private transient BaseCalendar.Date cdate;
149
150     // Initialized just before the value is used. See parse().
151     private static int defaultCenturyStart;
152
153     /* use serialVersionUID from modified java.util.Date for
154      * interoperability with JDK1.1. The Date was modified to write
155      * and read only the UTC time.
156      */

157     private static final long serialVersionUID = 7523967970034938905L;
158
159     /**
160      * Allocates a {@code Date} object and initializes it so that
161      * it represents the time at which it was allocated, measured to the
162      * nearest millisecond.
163      *
164      * @see     java.lang.System#currentTimeMillis()
165      */

166     public Date() {
167         this(System.currentTimeMillis());
168     }
169
170     /**
171      * Allocates a {@code Date} object and initializes it to
172      * represent the specified number of milliseconds since the
173      * standard base time known as "the epoch", namely January 1,
174      * 1970, 00:00:00 GMT.
175      *
176      * @param   date   the milliseconds since January 1, 1970, 00:00:00 GMT.
177      * @see     java.lang.System#currentTimeMillis()
178      */

179     public Date(long date) {
180         fastTime = date;
181     }
182
183     /**
184      * Allocates a {@code Date} object and initializes it so that
185      * it represents midnight, local time, at the beginning of the day
186      * specified by the {@code year}, {@code month}, and
187      * {@code date} arguments.
188      *
189      * @param   year    the year minus 1900.
190      * @param   month   the month between 0-11.
191      * @param   date    the day of the month between 1-31.
192      * @see     java.util.Calendar
193      * @deprecated As of JDK version 1.1,
194      * replaced by {@code Calendar.set(year + 1900, month, date)}
195      * or {@code GregorianCalendar(year + 1900, month, date)}.
196      */

197     @Deprecated
198     public Date(int year, int month, int date) {
199         this(year, month, date, 0, 0, 0);
200     }
201
202     /**
203      * Allocates a {@code Date} object and initializes it so that
204      * it represents the instant at the start of the minute specified by
205      * the {@code year}, {@code month}, {@code date},
206      * {@code hrs}, and {@code min} arguments, in the local
207      * time zone.
208      *
209      * @param   year    the year minus 1900.
210      * @param   month   the month between 0-11.
211      * @param   date    the day of the month between 1-31.
212      * @param   hrs     the hours between 0-23.
213      * @param   min     the minutes between 0-59.
214      * @see     java.util.Calendar
215      * @deprecated As of JDK version 1.1,
216      * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min)}
217      * or {@code GregorianCalendar(year + 1900, month, date, hrs, min)}.
218      */

219     @Deprecated
220     public Date(int year, int month, int date, int hrs, int min) {
221         this(year, month, date, hrs, min, 0);
222     }
223
224     /**
225      * Allocates a {@code Date} object and initializes it so that
226      * it represents the instant at the start of the second specified
227      * by the {@code year}, {@code month}, {@code date},
228      * {@code hrs}, {@code min}, and {@code sec} arguments,
229      * in the local time zone.
230      *
231      * @param   year    the year minus 1900.
232      * @param   month   the month between 0-11.
233      * @param   date    the day of the month between 1-31.
234      * @param   hrs     the hours between 0-23.
235      * @param   min     the minutes between 0-59.
236      * @param   sec     the seconds between 0-59.
237      * @see     java.util.Calendar
238      * @deprecated As of JDK version 1.1,
239      * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min, sec)}
240      * or {@code GregorianCalendar(year + 1900, month, date, hrs, min, sec)}.
241      */

242     @Deprecated
243     public Date(int year, int month, int date, int hrs, int min, int sec) {
244         int y = year + 1900;
245         // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
246         if (month >= 12) {
247             y += month / 12;
248             month %= 12;
249         } else if (month < 0) {
250             y += CalendarUtils.floorDivide(month, 12);
251             month = CalendarUtils.mod(month, 12);
252         }
253         BaseCalendar cal = getCalendarSystem(y);
254         cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
255         cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs, min, sec, 0);
256         getTimeImpl();
257         cdate = null;
258     }
259
260     /**
261      * Allocates a {@code Date} object and initializes it so that
262      * it represents the date and time indicated by the string
263      * {@code s}, which is interpreted as if by the
264      * {@link Date#parse} method.
265      *
266      * @param   s   a string representation of the date.
267      * @see     java.text.DateFormat
268      * @see     java.util.Date#parse(java.lang.String)
269      * @deprecated As of JDK version 1.1,
270      * replaced by {@code DateFormat.parse(String s)}.
271      */

272     @Deprecated
273     public Date(String s) {
274         this(parse(s));
275     }
276
277     /**
278      * Return a copy of this object.
279      */

280     public Object clone() {
281         Date d = null;
282         try {
283             d = (Date)super.clone();
284             if (cdate != null) {
285                 d.cdate = (BaseCalendar.Date) cdate.clone();
286             }
287         } catch (CloneNotSupportedException e) {} // Won't happen
288         return d;
289     }
290
291     /**
292      * Determines the date and time based on the arguments. The
293      * arguments are interpreted as a year, month, day of the month,
294      * hour of the day, minute within the hour, and second within the
295      * minute, exactly as for the {@code Date} constructor with six
296      * arguments, except that the arguments are interpreted relative
297      * to UTC rather than to the local time zone. The time indicated is
298      * returned represented as the distance, measured in milliseconds,
299      * of that time from the epoch (00:00:00 GMT on January 1, 1970).
300      *
301      * @param   year    the year minus 1900.
302      * @param   month   the month between 0-11.
303      * @param   date    the day of the month between 1-31.
304      * @param   hrs     the hours between 0-23.
305      * @param   min     the minutes between 0-59.
306      * @param   sec     the seconds between 0-59.
307      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT for
308      *          the date and time specified by the arguments.
309      * @see     java.util.Calendar
310      * @deprecated As of JDK version 1.1,
311      * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min, sec)}
312      * or {@code GregorianCalendar(year + 1900, month, date, hrs, min, sec)}, using a UTC
313      * {@code TimeZone}, followed by {@code Calendar.getTime().getTime()}.
314      */

315     @Deprecated
316     public static long UTC(int year, int month, int date,
317                            int hrs, int min, int sec) {
318         int y = year + 1900;
319         // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
320         if (month >= 12) {
321             y += month / 12;
322             month %= 12;
323         } else if (month < 0) {
324             y += CalendarUtils.floorDivide(month, 12);
325             month = CalendarUtils.mod(month, 12);
326         }
327         int m = month + 1;
328         BaseCalendar cal = getCalendarSystem(y);
329         BaseCalendar.Date udate = (BaseCalendar.Date) cal.newCalendarDate(null);
330         udate.setNormalizedDate(y, m, date).setTimeOfDay(hrs, min, sec, 0);
331
332         // Use a Date instance to perform normalization. Its fastTime
333         // is the UTC value after the normalization.
334         Date d = new Date(0);
335         d.normalize(udate);
336         return d.fastTime;
337     }
338
339     /**
340      * Attempts to interpret the string {@code s} as a representation
341      * of a date and time. If the attempt is successful, the time
342      * indicated is returned represented as the distance, measured in
343      * milliseconds, of that time from the epoch (00:00:00 GMT on
344      * January 1, 1970). If the attempt fails, an
345      * {@code IllegalArgumentException} is thrown.
346      * <p>
347      * It accepts many syntaxes; in particular, it recognizes the IETF
348      * standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also
349      * understands the continental U.S. time-zone abbreviations, but for
350      * general use, a time-zone offset should be used: "Sat, 12 Aug 1995
351      * 13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich
352      * meridian). If no time zone is specified, the local time zone is
353      * assumed. GMT and UTC are considered equivalent.
354      * <p>
355      * The string {@code s} is processed from left to right, looking for
356      * data of interest. Any material in {@code s} that is within the
357      * ASCII parenthesis characters {@code (} and {@code )} is ignored.
358      * Parentheses may be nested. Otherwise, the only characters permitted
359      * within {@code s} are these ASCII characters:
360      * <blockquote><pre>
361      * abcdefghijklmnopqrstuvwxyz
362      * ABCDEFGHIJKLMNOPQRSTUVWXYZ
363      * 0123456789,+-:/</pre></blockquote>
364      * and whitespace characters.<p>
365      * A consecutive sequence of decimal digits is treated as a decimal
366      * number:<ul>
367      * <li>If a number is preceded by {@code +} or {@code -} and a year
368      *     has already been recognized, then the number is a time-zone
369      *     offset. If the number is less than 24, it is an offset measured
370      *     in hours. Otherwise, it is regarded as an offset in minutes,
371      *     expressed in 24-hour time format without punctuation. A
372      *     preceding {@code -} means a westward offset. Time zone offsets
373      *     are always relative to UTC (Greenwich). Thus, for example,
374      *     {@code -5} occurring in the string would mean "five hours west
375      *     of Greenwich" and {@code +0430} would mean "four hours and
376      *     thirty minutes east of Greenwich." It is permitted for the
377      *     string to specify {@code GMT}, {@code UT}, or {@code UTC}
378      *     redundantly-for example, {@code GMT-5} or {@code utc+0430}.
379      * <li>The number is regarded as a year number if one of the
380      *     following conditions is true:
381      * <ul>
382      *     <li>The number is equal to or greater than 70 and followed by a
383      *         space, comma, slash, or end of string
384      *     <li>The number is less than 70, and both a month and a day of
385      *         the month have already been recognized</li>
386      * </ul>
387      *     If the recognized year number is less than 100, it is
388      *     interpreted as an abbreviated year relative to a century of
389      *     which dates are within 80 years before and 19 years after
390      *     the time when the Date class is initialized.
391      *     After adjusting the year number, 1900 is subtracted from
392      *     it. For example, if the current year is 1999 then years in
393      *     the range 19 to 99 are assumed to mean 1919 to 1999, while
394      *     years from 0 to 18 are assumed to mean 2000 to 2018.  Note
395      *     that this is slightly different from the interpretation of
396      *     years less than 100 that is used in {@link java.text.SimpleDateFormat}.
397      * <li>If the number is followed by a colon, it is regarded as an hour,
398      *     unless an hour has already been recognized, in which case it is
399      *     regarded as a minute.
400      * <li>If the number is followed by a slash, it is regarded as a month
401      *     (it is decreased by 1 to produce a number in the range {@code 0}
402      *     to {@code 11}), unless a month has already been recognized, in
403      *     which case it is regarded as a day of the month.
404      * <li>If the number is followed by whitespace, a comma, a hyphen, or
405      *     end of string, then if an hour has been recognized but not a
406      *     minute, it is regarded as a minute; otherwise, if a minute has
407      *     been recognized but not a second, it is regarded as a second;
408      *     otherwise, it is regarded as a day of the month. </ul><p>
409      * A consecutive sequence of letters is regarded as a word and treated
410      * as follows:<ul>
411      * <li>A word that matches {@code AM}, ignoring case, is ignored (but
412      *     the parse fails if an hour has not been recognized or is less
413      *     than {@code 1} or greater than {@code 12}).
414      * <li>A word that matches {@code PM}, ignoring case, adds {@code 12}
415      *     to the hour (but the parse fails if an hour has not been
416      *     recognized or is less than {@code 1} or greater than {@code 12}).
417      * <li>Any word that matches any prefix of {@code SUNDAY, MONDAY, TUESDAY,
418      *     WEDNESDAY, THURSDAY, FRIDAY}, or {@code SATURDAY}, ignoring
419      *     case, is ignored. For example, {@code sat, Friday, TUE}, and
420      *     {@code Thurs} are ignored.
421      * <li>Otherwise, any word that matches any prefix of {@code JANUARY,
422      *     FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,
423      *     OCTOBER, NOVEMBER}, or {@code DECEMBER}, ignoring case, and
424      *     considering them in the order given here, is recognized as
425      *     specifying a month and is converted to a number ({@code 0} to
426      *     {@code 11}). For example, {@code aug, Sept, april}, and
427      *     {@code NOV} are recognized as months. So is {@code Ma}, which
428      *     is recognized as {@code MARCH}, not {@code MAY}.
429      * <li>Any word that matches {@code GMT, UT}, or {@code UTC}, ignoring
430      *     case, is treated as referring to UTC.
431      * <li>Any word that matches {@code EST, CST, MST}, or {@code PST},
432      *     ignoring case, is recognized as referring to the time zone in
433      *     North America that is five, six, seven, or eight hours west of
434      *     Greenwich, respectively. Any word that matches {@code EDT, CDT,
435      *     MDT}, or {@code PDT}, ignoring case, is recognized as
436      *     referring to the same time zone, respectively, during daylight
437      *     saving time.</ul><p>
438      * Once the entire string s has been scanned, it is converted to a time
439      * result in one of two ways. If a time zone or time-zone offset has been
440      * recognized, then the year, month, day of month, hour, minute, and
441      * second are interpreted in UTC and then the time-zone offset is
442      * applied. Otherwise, the year, month, day of month, hour, minute, and
443      * second are interpreted in the local time zone.
444      *
445      * @param   s   a string to be parsed as a date.
446      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
447      *          represented by the string argument.
448      * @see     java.text.DateFormat
449      * @deprecated As of JDK version 1.1,
450      * replaced by {@code DateFormat.parse(String s)}.
451      */

452     @Deprecated
453     public static long parse(String s) {
454         int year = Integer.MIN_VALUE;
455         int mon = -1;
456         int mday = -1;
457         int hour = -1;
458         int min = -1;
459         int sec = -1;
460         int millis = -1;
461         int c = -1;
462         int i = 0;
463         int n = -1;
464         int wst = -1;
465         int tzoffset = -1;
466         int prevc = 0;
467     syntax:
468         {
469             if (s == null)
470                 break syntax;
471             int limit = s.length();
472             while (i < limit) {
473                 c = s.charAt(i);
474                 i++;
475                 if (c <= ' ' || c == ',')
476                     continue;
477                 if (c == '(') { // skip comments
478                     int depth = 1;
479                     while (i < limit) {
480                         c = s.charAt(i);
481                         i++;
482                         if (c == '(') depth++;
483                         else if (c == ')')
484                             if (--depth <= 0)
485                                 break;
486                     }
487                     continue;
488                 }
489                 if ('0' <= c && c <= '9') {
490                     n = c - '0';
491                     while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
492                         n = n * 10 + c - '0';
493                         i++;
494                     }
495                     if (prevc == '+' || prevc == '-' && year != Integer.MIN_VALUE) {
496                         // timezone offset
497                         if (n < 24)
498                             n = n * 60; // EG. "GMT-3"
499                         else
500                             n = n % 100 + n / 100 * 60; // eg "GMT-0430"
501                         if (prevc == '+')   // plus means east of GMT
502                             n = -n;
503                         if (tzoffset != 0 && tzoffset != -1)
504                             break syntax;
505                         tzoffset = n;
506                     } else if (n >= 70)
507                         if (year != Integer.MIN_VALUE)
508                             break syntax;
509                         else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
510                             // year = n < 1900 ? n : n - 1900;
511                             year = n;
512                         else
513                             break syntax;
514                     else if (c == ':')
515                         if (hour < 0)
516                             hour = (byte) n;
517                         else if (min < 0)
518                             min = (byte) n;
519                         else
520                             break syntax;
521                     else if (c == '/')
522                         if (mon < 0)
523                             mon = (byte) (n - 1);
524                         else if (mday < 0)
525                             mday = (byte) n;
526                         else
527                             break syntax;
528                     else if (i < limit && c != ',' && c > ' ' && c != '-')
529                         break syntax;
530                     else if (hour >= 0 && min < 0)
531                         min = (byte) n;
532                     else if (min >= 0 && sec < 0)
533                         sec = (byte) n;
534                     else if (mday < 0)
535                         mday = (byte) n;
536                     // Handle two-digit years < 70 (70-99 handled above).
537                     else if (year == Integer.MIN_VALUE && mon >= 0 && mday >= 0)
538                         year = n;
539                     else
540                         break syntax;
541                     prevc = 0;
542                 } else if (c == '/' || c == ':' || c == '+' || c == '-')
543                     prevc = c;
544                 else {
545                     int st = i - 1;
546                     while (i < limit) {
547                         c = s.charAt(i);
548                         if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'))
549                             break;
550                         i++;
551                     }
552                     if (i <= st + 1)
553                         break syntax;
554                     int k;
555                     for (k = wtb.length; --k >= 0;)
556                         if (wtb[k].regionMatches(true, 0, s, st, i - st)) {
557                             int action = ttb[k];
558                             if (action != 0) {
559                                 if (action == 1) {  // pm
560                                     if (hour > 12 || hour < 1)
561                                         break syntax;
562                                     else if (hour < 12)
563                                         hour += 12;
564                                 } else if (action == 14) {  // am
565                                     if (hour > 12 || hour < 1)
566                                         break syntax;
567                                     else if (hour == 12)
568                                         hour = 0;
569                                 } else if (action <= 13) {  // month!
570                                     if (mon < 0)
571                                         mon = (byte) (action - 2);
572                                     else
573                                         break syntax;
574                                 } else {
575                                     tzoffset = action - 10000;
576                                 }
577                             }
578                             break;
579                         }
580                     if (k < 0)
581                         break syntax;
582                     prevc = 0;
583                 }
584             }
585             if (year == Integer.MIN_VALUE || mon < 0 || mday < 0)
586                 break syntax;
587             // Parse 2-digit years within the correct default century.
588             if (year < 100) {
589                 synchronized (Date.class) {
590                     if (defaultCenturyStart == 0) {
591                         defaultCenturyStart = gcal.getCalendarDate().getYear() - 80;
592                     }
593                 }
594                 year += (defaultCenturyStart / 100) * 100;
595                 if (year < defaultCenturyStart) year += 100;
596             }
597             if (sec < 0)
598                 sec = 0;
599             if (min < 0)
600                 min = 0;
601             if (hour < 0)
602                 hour = 0;
603             BaseCalendar cal = getCalendarSystem(year);
604             if (tzoffset == -1)  { // no time zone specified, have to use local
605                 BaseCalendar.Date ldate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
606                 ldate.setDate(year, mon + 1, mday);
607                 ldate.setTimeOfDay(hour, min, sec, 0);
608                 return cal.getTime(ldate);
609             }
610             BaseCalendar.Date udate = (BaseCalendar.Date) cal.newCalendarDate(null); // no time zone
611             udate.setDate(year, mon + 1, mday);
612             udate.setTimeOfDay(hour, min, sec, 0);
613             return cal.getTime(udate) + tzoffset * (60 * 1000);
614         }
615         // syntax error
616         throw new IllegalArgumentException();
617     }
618     private static final String wtb[] = {
619         "am""pm",
620         "monday""tuesday""wednesday""thursday""friday",
621         "saturday""sunday",
622         "january""february""march""april""may""june",
623         "july""august""september""october""november""december",
624         "gmt""ut""utc""est""edt""cst""cdt",
625         "mst""mdt""pst""pdt"
626     };
627     private static final int ttb[] = {
628         14, 1, 0, 0, 0, 0, 0, 0, 0,
629         2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
630         10000 + 0, 10000 + 0, 10000 + 0,    // GMT/UT/UTC
631         10000 + 5 * 60, 10000 + 4 * 60,     // EST/EDT
632         10000 + 6 * 60, 10000 + 5 * 60,     // CST/CDT
633         10000 + 7 * 60, 10000 + 6 * 60,     // MST/MDT
634         10000 + 8 * 60, 10000 + 7 * 60      // PST/PDT
635     };
636
637     /**
638      * Returns a value that is the result of subtracting 1900 from the
639      * year that contains or begins with the instant in time represented
640      * by this {@code Date} object, as interpreted in the local
641      * time zone.
642      *
643      * @return  the year represented by this date, minus 1900.
644      * @see     java.util.Calendar
645      * @deprecated As of JDK version 1.1,
646      * replaced by {@code Calendar.get(Calendar.YEAR) - 1900}.
647      */

648     @Deprecated
649     public int getYear() {
650         return normalize().getYear() - 1900;
651     }
652
653     /**
654      * Sets the year of this {@code Date} object to be the specified
655      * value plus 1900. This {@code Date} object is modified so
656      * that it represents a point in time within the specified year,
657      * with the month, date, hour, minute, and second the same as
658      * before, as interpreted in the local time zone. (Of course, if
659      * the date was February 29, for example, and the year is set to a
660      * non-leap year, then the new date will be treated as if it were
661      * on March 1.)
662      *
663      * @param   year    the year value.
664      * @see     java.util.Calendar
665      * @deprecated As of JDK version 1.1,
666      * replaced by {@code Calendar.set(Calendar.YEAR, year + 1900)}.
667      */

668     @Deprecated
669     public void setYear(int year) {
670         getCalendarDate().setNormalizedYear(year + 1900);
671     }
672
673     /**
674      * Returns a number representing the month that contains or begins
675      * with the instant in time represented by this {@code Date} object.
676      * The value returned is between {@code 0} and {@code 11},
677      * with the value {@code 0} representing January.
678      *
679      * @return  the month represented by this date.
680      * @see     java.util.Calendar
681      * @deprecated As of JDK version 1.1,
682      * replaced by {@code Calendar.get(Calendar.MONTH)}.
683      */

684     @Deprecated
685     public int getMonth() {
686         return normalize().getMonth() - 1; // adjust 1-based to 0-based
687     }
688
689     /**
690      * Sets the month of this date to the specified value. This
691      * {@code Date} object is modified so that it represents a point
692      * in time within the specified month, with the year, date, hour,
693      * minute, and second the same as before, as interpreted in the
694      * local time zone. If the date was October 31, for example, and
695      * the month is set to June, then the new date will be treated as
696      * if it were on July 1, because June has only 30 days.
697      *
698      * @param   month   the month value between 0-11.
699      * @see     java.util.Calendar
700      * @deprecated As of JDK version 1.1,
701      * replaced by {@code Calendar.set(Calendar.MONTH, int month)}.
702      */

703     @Deprecated
704     public void setMonth(int month) {
705         int y = 0;
706         if (month >= 12) {
707             y = month / 12;
708             month %= 12;
709         } else if (month < 0) {
710             y = CalendarUtils.floorDivide(month, 12);
711             month = CalendarUtils.mod(month, 12);
712         }
713         BaseCalendar.Date d = getCalendarDate();
714         if (y != 0) {
715             d.setNormalizedYear(d.getNormalizedYear() + y);
716         }
717         d.setMonth(month + 1); // adjust 0-based to 1-based month numbering
718     }
719
720     /**
721      * Returns the day of the month represented by this {@code Date} object.
722      * The value returned is between {@code 1} and {@code 31}
723      * representing the day of the month that contains or begins with the
724      * instant in time represented by this {@code Date} object, as
725      * interpreted in the local time zone.
726      *
727      * @return  the day of the month represented by this date.
728      * @see     java.util.Calendar
729      * @deprecated As of JDK version 1.1,
730      * replaced by {@code Calendar.get(Calendar.DAY_OF_MONTH)}.
731      */

732     @Deprecated
733     public int getDate() {
734         return normalize().getDayOfMonth();
735     }
736
737     /**
738      * Sets the day of the month of this {@code Date} object to the
739      * specified value. This {@code Date} object is modified so that
740      * it represents a point in time within the specified day of the
741      * month, with the year, month, hour, minute, and second the same
742      * as before, as interpreted in the local time zone. If the date
743      * was April 30, for example, and the date is set to 31, then it
744      * will be treated as if it were on May 1, because April has only
745      * 30 days.
746      *
747      * @param   date   the day of the month value between 1-31.
748      * @see     java.util.Calendar
749      * @deprecated As of JDK version 1.1,
750      * replaced by {@code Calendar.set(Calendar.DAY_OF_MONTH, int date)}.
751      */

752     @Deprecated
753     public void setDate(int date) {
754         getCalendarDate().setDayOfMonth(date);
755     }
756
757     /**
758      * Returns the day of the week represented by this date. The
759      * returned value ({@code 0} = Sunday, {@code 1} = Monday,
760      * {@code 2} = Tuesday, {@code 3} = Wednesday, {@code 4} =
761      * Thursday, {@code 5} = Friday, {@code 6} = Saturday)
762      * represents the day of the week that contains or begins with
763      * the instant in time represented by this {@code Date} object,
764      * as interpreted in the local time zone.
765      *
766      * @return  the day of the week represented by this date.
767      * @see     java.util.Calendar
768      * @deprecated As of JDK version 1.1,
769      * replaced by {@code Calendar.get(Calendar.DAY_OF_WEEK)}.
770      */

771     @Deprecated
772     public int getDay() {
773         return normalize().getDayOfWeek() - BaseCalendar.SUNDAY;
774     }
775
776     /**
777      * Returns the hour represented by this {@code Date} object. The
778      * returned value is a number ({@code 0} through {@code 23})
779      * representing the hour within the day that contains or begins
780      * with the instant in time represented by this {@code Date}
781      * object, as interpreted in the local time zone.
782      *
783      * @return  the hour represented by this date.
784      * @see     java.util.Calendar
785      * @deprecated As of JDK version 1.1,
786      * replaced by {@code Calendar.get(Calendar.HOUR_OF_DAY)}.
787      */

788     @Deprecated
789     public int getHours() {
790         return normalize().getHours();
791     }
792
793     /**
794      * Sets the hour of this {@code Date} object to the specified value.
795      * This {@code Date} object is modified so that it represents a point
796      * in time within the specified hour of the day, with the year, month,
797      * date, minute, and second the same as before, as interpreted in the
798      * local time zone.
799      *
800      * @param   hours   the hour value.
801      * @see     java.util.Calendar
802      * @deprecated As of JDK version 1.1,
803      * replaced by {@code Calendar.set(Calendar.HOUR_OF_DAY, int hours)}.
804      */

805     @Deprecated
806     public void setHours(int hours) {
807         getCalendarDate().setHours(hours);
808     }
809
810     /**
811      * Returns the number of minutes past the hour represented by this date,
812      * as interpreted in the local time zone.
813      * The value returned is between {@code 0} and {@code 59}.
814      *
815      * @return  the number of minutes past the hour represented by this date.
816      * @see     java.util.Calendar
817      * @deprecated As of JDK version 1.1,
818      * replaced by {@code Calendar.get(Calendar.MINUTE)}.
819      */

820     @Deprecated
821     public int getMinutes() {
822         return normalize().getMinutes();
823     }
824
825     /**
826      * Sets the minutes of this {@code Date} object to the specified value.
827      * This {@code Date} object is modified so that it represents a point
828      * in time within the specified minute of the hour, with the year, month,
829      * date, hour, and second the same as before, as interpreted in the
830      * local time zone.
831      *
832      * @param   minutes   the value of the minutes.
833      * @see     java.util.Calendar
834      * @deprecated As of JDK version 1.1,
835      * replaced by {@code Calendar.set(Calendar.MINUTE, int minutes)}.
836      */

837     @Deprecated
838     public void setMinutes(int minutes) {
839         getCalendarDate().setMinutes(minutes);
840     }
841
842     /**
843      * Returns the number of seconds past the minute represented by this date.
844      * The value returned is between {@code 0} and {@code 61}. The
845      * values {@code 60} and {@code 61} can only occur on those
846      * Java Virtual Machines that take leap seconds into account.
847      *
848      * @return  the number of seconds past the minute represented by this date.
849      * @see     java.util.Calendar
850      * @deprecated As of JDK version 1.1,
851      * replaced by {@code Calendar.get(Calendar.SECOND)}.
852      */

853     @Deprecated
854     public int getSeconds() {
855         return normalize().getSeconds();
856     }
857
858     /**
859      * Sets the seconds of this {@code Date} to the specified value.
860      * This {@code Date} object is modified so that it represents a
861      * point in time within the specified second of the minute, with
862      * the year, month, date, hour, and minute the same as before, as
863      * interpreted in the local time zone.
864      *
865      * @param   seconds   the seconds value.
866      * @see     java.util.Calendar
867      * @deprecated As of JDK version 1.1,
868      * replaced by {@code Calendar.set(Calendar.SECOND, int seconds)}.
869      */

870     @Deprecated
871     public void setSeconds(int seconds) {
872         getCalendarDate().setSeconds(seconds);
873     }
874
875     /**
876      * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
877      * represented by this {@code Date} object.
878      *
879      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
880      *          represented by this date.
881      */

882     public long getTime() {
883         return getTimeImpl();
884     }
885
886     private final long getTimeImpl() {
887         if (cdate != null && !cdate.isNormalized()) {
888             normalize();
889         }
890         return fastTime;
891     }
892
893     /**
894      * Sets this {@code Date} object to represent a point in time that is
895      * {@code time} milliseconds after January 1, 1970 00:00:00 GMT.
896      *
897      * @param   time   the number of milliseconds.
898      */

899     public void setTime(long time) {
900         fastTime = time;
901         cdate = null;
902     }
903
904     /**
905      * Tests if this date is before the specified date.
906      *
907      * @param   when   a date.
908      * @return  {@code trueif 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 trueif 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 trueif 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 trueif 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