• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.util;
28 
29 import java.text.DateFormat;
30 import java.io.IOException;
31 import java.io.ObjectOutputStream;
32 import java.io.ObjectInputStream;
33 import java.time.Instant;
34 import sun.util.calendar.BaseCalendar;
35 import sun.util.calendar.CalendarSystem;
36 import sun.util.calendar.CalendarUtils;
37 import sun.util.calendar.Era;
38 import sun.util.calendar.Gregorian;
39 
40 /**
41  * The class {@code Date} represents a specific instant
42  * in time, with millisecond precision.
43  * <p>
44  * Prior to JDK&nbsp;1.1, the class {@code Date} had two additional
45  * functions.  It allowed the interpretation of dates as year, month, day, hour,
46  * minute, and second values.  It also allowed the formatting and parsing
47  * of date strings.  Unfortunately, the API for these functions was not
48  * amenable to internationalization.  As of JDK&nbsp;1.1, the
49  * {@code Calendar} class should be used to convert between dates and time
50  * fields and the {@code DateFormat} class should be used to format and
51  * parse date strings.
52  * The corresponding methods in {@code Date} are deprecated.
53  * <p>
54  * Although the {@code Date} class is intended to reflect
55  * coordinated universal time (UTC), it may not do so exactly,
56  * depending on the host environment of the Java Virtual Machine.
57  * Nearly all modern operating systems assume that 1&nbsp;day&nbsp;=
58  * 24&nbsp;&times;&nbsp;60&nbsp;&times;&nbsp;60&nbsp;= 86400 seconds
59  * in all cases. In UTC, however, about once every year or two there
60  * is an extra second, called a "leap second." The leap
61  * second is always added as the last second of the day, and always
62  * on December 31 or June 30. For example, the last minute of the
63  * year 1995 was 61 seconds long, thanks to an added leap second.
64  * Most computer clocks are not accurate enough to be able to reflect
65  * the leap-second distinction.
66  * <p>
67  * Some computer standards are defined in terms of Greenwich mean
68  * time (GMT), which is equivalent to universal time (UT).  GMT is
69  * the "civil" name for the standard; UT is the
70  * "scientific" name for the same standard. The
71  * distinction between UTC and UT is that UTC is based on an atomic
72  * clock and UT is based on astronomical observations, which for all
73  * practical purposes is an invisibly fine hair to split. Because the
74  * earth's rotation is not uniform (it slows down and speeds up
75  * in complicated ways), UT does not always flow uniformly. Leap
76  * seconds are introduced as needed into UTC so as to keep UTC within
77  * 0.9 seconds of UT1, which is a version of UT with certain
78  * corrections applied. There are other time and date systems as
79  * well; for example, the time scale used by the satellite-based
80  * global positioning system (GPS) is synchronized to UTC but is
81  * <i>not</i> adjusted for leap seconds. An interesting source of
82  * further information is the United States Naval Observatory (USNO):
83  * <blockquote><pre>
84  *     <a href="https://www.usno.navy.mil/USNO">https://www.usno.navy.mil/USNO</a>
85  * </pre></blockquote>
86  * <p>
87  * and the material regarding "Systems of Time" at:
88  * <blockquote><pre>
89  *     <a href="https://www.usno.navy.mil/USNO/time/master-clock/systems-of-time">https://www.usno.navy.mil/USNO/time/master-clock/systems-of-time</a>
90  * </pre></blockquote>
91  * <p>
92  * which has descriptions of various different time systems including
93  * UT, UT1, and UTC.
94  * <p>
95  * In all methods of class {@code Date} that accept or return
96  * year, month, date, hours, minutes, and seconds values, the
97  * following representations are used:
98  * <ul>
99  * <li>A year <i>y</i> is represented by the integer
100  *     <i>y</i>&nbsp;{@code - 1900}.
101  * <li>A month is represented by an integer from 0 to 11; 0 is January,
102  *     1 is February, and so forth; thus 11 is December.
103  * <li>A date (day of month) is represented by an integer from 1 to 31
104  *     in the usual manner.
105  * <li>An hour is represented by an integer from 0 to 23. Thus, the hour
106  *     from midnight to 1 a.m. is hour 0, and the hour from noon to 1
107  *     p.m. is hour 12.
108  * <li>A minute is represented by an integer from 0 to 59 in the usual manner.
109  * <li>A second is represented by an integer from 0 to 61; the values 60 and
110  *     61 occur only for leap seconds and even then only in Java
111  *     implementations that actually track leap seconds correctly. Because
112  *     of the manner in which leap seconds are currently introduced, it is
113  *     extremely unlikely that two leap seconds will occur in the same
114  *     minute, but this specification follows the date and time conventions
115  *     for ISO C.
116  * </ul>
117  * <p>
118  * In all cases, arguments given to methods for these purposes need
119  * not fall within the indicated ranges; for example, a date may be
120  * specified as January 32 and is interpreted as meaning February 1.
121  *
122  * @author  James Gosling
123  * @author  Arthur van Hoff
124  * @author  Alan Liu
125  * @see     java.text.DateFormat
126  * @see     java.util.Calendar
127  * @see     java.util.TimeZone
128  * @since   1.0
129  */
130 public class Date
131     implements java.io.Serializable, Cloneable, Comparable<Date>
132 {
133     private static final BaseCalendar gcal =
134                                 CalendarSystem.getGregorianCalendar();
135     private static BaseCalendar jcal;
136 
137     private transient long fastTime;
138 
139     /*
140      * If cdate is null, then fastTime indicates the time in millis.
141      * If cdate.isNormalized() is true, then fastTime and cdate are in
142      * synch. Otherwise, fastTime is ignored, and cdate indicates the
143      * time.
144      */
145     private transient BaseCalendar.Date cdate;
146 
147     // Initialized just before the value is used. See parse().
148     private static int defaultCenturyStart;
149 
150     /* use serialVersionUID from modified java.util.Date for
151      * interoperability with JDK1.1. The Date was modified to write
152      * and read only the UTC time.
153      */
154     @java.io.Serial
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      */
Date()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      */
Date(long date)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
Date(int year, int month, int date)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
Date(int year, int month, int date, int hrs, int min)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
Date(int year, int month, int date, int hrs, int min, int sec)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      * @throws IllegalArgumentException if {@code s} cannot be interpreted as a
266      * representation of a date and time.
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
Date(String s)273     public Date(String s) {
274         this(parse(s));
275     }
276 
277     /**
278      * Return a copy of this object.
279      */
clone()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
UTC(int year, int month, int date, int hrs, int min, int sec)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      * @throws IllegalArgumentException if {@code s} cannot be interpreted as a
449      * representation of a date and time.
450      * @see     java.text.DateFormat
451      * @deprecated As of JDK version 1.1,
452      * replaced by {@code DateFormat.parse(String s)}.
453      */
454     @Deprecated
parse(String s)455     public static long parse(String s) {
456         int year = Integer.MIN_VALUE;
457         int mon = -1;
458         int mday = -1;
459         int hour = -1;
460         int min = -1;
461         int sec = -1;
462         int millis = -1;
463         int c = -1;
464         int i = 0;
465         int n = -1;
466         int wst = -1;
467         int tzoffset = -1;
468         int prevc = 0;
469     syntax:
470         {
471             if (s == null)
472                 break syntax;
473             int limit = s.length();
474             while (i < limit) {
475                 c = s.charAt(i);
476                 i++;
477                 if (c <= ' ' || c == ',')
478                     continue;
479                 if (c == '(') { // skip comments
480                     int depth = 1;
481                     while (i < limit) {
482                         c = s.charAt(i);
483                         i++;
484                         if (c == '(') depth++;
485                         else if (c == ')')
486                             if (--depth <= 0)
487                                 break;
488                     }
489                     continue;
490                 }
491                 if ('0' <= c && c <= '9') {
492                     n = c - '0';
493                     while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
494                         n = n * 10 + c - '0';
495                         i++;
496                     }
497                     if (prevc == '+' || prevc == '-' && year != Integer.MIN_VALUE) {
498                         // BEGIN Android-changed: Android specific time zone logic
499 
500                         if (tzoffset != 0 && tzoffset != -1)
501                             break syntax;
502 
503                         // timezone offset
504                         if (n < 24) {
505                             n = n * 60; // EG. "GMT-3"
506 
507                             // Support for Timezones of the form GMT-3:30. We look for an ':" and
508                             // parse the number following it as loosely as the original hours
509                             // section (i.e, no range or validity checks).
510                             int minutesPart = 0;
511                             if (i < limit && (s.charAt(i) == ':')) {
512                                 i++;
513                                 while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
514                                     minutesPart = (minutesPart * 10) + (c - '0');
515                                     i++;
516                                 }
517                             }
518 
519                             n += minutesPart;
520                         } else {
521                             n = (n % 100) + ((n / 100) * 60); // eg "GMT-0430"
522                         }
523 
524                         if (prevc == '+')   // plus means east of GMT
525                             n = -n;
526                         // END Android-changed: Android specific time zone logic
527 
528                         tzoffset = n;
529                     } else if (n >= 70)
530                         if (year != Integer.MIN_VALUE)
531                             break syntax;
532                         else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
533                             // year = n < 1900 ? n : n - 1900;
534                             year = n;
535                         else
536                             break syntax;
537                     else if (c == ':')
538                         if (hour < 0)
539                             hour = (byte) n;
540                         else if (min < 0)
541                             min = (byte) n;
542                         else
543                             break syntax;
544                     else if (c == '/')
545                         if (mon < 0)
546                             mon = (byte) (n - 1);
547                         else if (mday < 0)
548                             mday = (byte) n;
549                         else
550                             break syntax;
551                     else if (i < limit && c != ',' && c > ' ' && c != '-')
552                         break syntax;
553                     else if (hour >= 0 && min < 0)
554                         min = (byte) n;
555                     else if (min >= 0 && sec < 0)
556                         sec = (byte) n;
557                     else if (mday < 0)
558                         mday = (byte) n;
559                     // Handle two-digit years < 70 (70-99 handled above).
560                     else if (year == Integer.MIN_VALUE && mon >= 0 && mday >= 0)
561                         year = n;
562                     else
563                         break syntax;
564                     prevc = 0;
565                 } else if (c == '/' || c == ':' || c == '+' || c == '-')
566                     prevc = c;
567                 else {
568                     int st = i - 1;
569                     while (i < limit) {
570                         c = s.charAt(i);
571                         if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'))
572                             break;
573                         i++;
574                     }
575                     if (i <= st + 1)
576                         break syntax;
577                     int k;
578                     for (k = wtb.length; --k >= 0;)
579                         if (wtb[k].regionMatches(true, 0, s, st, i - st)) {
580                             int action = ttb[k];
581                             if (action != 0) {
582                                 if (action == 1) {  // pm
583                                     if (hour > 12 || hour < 1)
584                                         break syntax;
585                                     else if (hour < 12)
586                                         hour += 12;
587                                 } else if (action == 14) {  // am
588                                     if (hour > 12 || hour < 1)
589                                         break syntax;
590                                     else if (hour == 12)
591                                         hour = 0;
592                                 } else if (action <= 13) {  // month!
593                                     if (mon < 0)
594                                         mon = (byte) (action - 2);
595                                     else
596                                         break syntax;
597                                 } else {
598                                     tzoffset = action - 10000;
599                                 }
600                             }
601                             break;
602                         }
603                     if (k < 0)
604                         break syntax;
605                     prevc = 0;
606                 }
607             }
608             if (year == Integer.MIN_VALUE || mon < 0 || mday < 0)
609                 break syntax;
610             // Parse 2-digit years within the correct default century.
611             if (year < 100) {
612                 synchronized (Date.class) {
613                     if (defaultCenturyStart == 0) {
614                         defaultCenturyStart = gcal.getCalendarDate().getYear() - 80;
615                     }
616                 }
617                 year += (defaultCenturyStart / 100) * 100;
618                 if (year < defaultCenturyStart) year += 100;
619             }
620             if (sec < 0)
621                 sec = 0;
622             if (min < 0)
623                 min = 0;
624             if (hour < 0)
625                 hour = 0;
626             BaseCalendar cal = getCalendarSystem(year);
627             if (tzoffset == -1)  { // no time zone specified, have to use local
628                 BaseCalendar.Date ldate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
629                 ldate.setDate(year, mon + 1, mday);
630                 ldate.setTimeOfDay(hour, min, sec, 0);
631                 return cal.getTime(ldate);
632             }
633             BaseCalendar.Date udate = (BaseCalendar.Date) cal.newCalendarDate(null); // no time zone
634             udate.setDate(year, mon + 1, mday);
635             udate.setTimeOfDay(hour, min, sec, 0);
636             return cal.getTime(udate) + tzoffset * (60 * 1000);
637         }
638         // syntax error
639         throw new IllegalArgumentException();
640     }
641     private static final String wtb[] = {
642         "am", "pm",
643         "monday", "tuesday", "wednesday", "thursday", "friday",
644         "saturday", "sunday",
645         "january", "february", "march", "april", "may", "june",
646         "july", "august", "september", "october", "november", "december",
647         "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
648         "mst", "mdt", "pst", "pdt"
649     };
650     private static final int ttb[] = {
651         14, 1, 0, 0, 0, 0, 0, 0, 0,
652         2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
653         10000 + 0, 10000 + 0, 10000 + 0,    // GMT/UT/UTC
654         10000 + 5 * 60, 10000 + 4 * 60,     // EST/EDT
655         10000 + 6 * 60, 10000 + 5 * 60,     // CST/CDT
656         10000 + 7 * 60, 10000 + 6 * 60,     // MST/MDT
657         10000 + 8 * 60, 10000 + 7 * 60      // PST/PDT
658     };
659 
660     /**
661      * Returns a value that is the result of subtracting 1900 from the
662      * year that contains or begins with the instant in time represented
663      * by this {@code Date} object, as interpreted in the local
664      * time zone.
665      *
666      * @return  the year represented by this date, minus 1900.
667      * @see     java.util.Calendar
668      * @deprecated As of JDK version 1.1,
669      * replaced by {@code Calendar.get(Calendar.YEAR) - 1900}.
670      */
671     @Deprecated
getYear()672     public int getYear() {
673         return normalize().getYear() - 1900;
674     }
675 
676     /**
677      * Sets the year of this {@code Date} object to be the specified
678      * value plus 1900. This {@code Date} object is modified so
679      * that it represents a point in time within the specified year,
680      * with the month, date, hour, minute, and second the same as
681      * before, as interpreted in the local time zone. (Of course, if
682      * the date was February 29, for example, and the year is set to a
683      * non-leap year, then the new date will be treated as if it were
684      * on March 1.)
685      *
686      * @param   year    the year value.
687      * @see     java.util.Calendar
688      * @deprecated As of JDK version 1.1,
689      * replaced by {@code Calendar.set(Calendar.YEAR, year + 1900)}.
690      */
691     @Deprecated
setYear(int year)692     public void setYear(int year) {
693         getCalendarDate().setNormalizedYear(year + 1900);
694     }
695 
696     /**
697      * Returns a number representing the month that contains or begins
698      * with the instant in time represented by this {@code Date} object.
699      * The value returned is between {@code 0} and {@code 11},
700      * with the value {@code 0} representing January.
701      *
702      * @return  the month represented by this date.
703      * @see     java.util.Calendar
704      * @deprecated As of JDK version 1.1,
705      * replaced by {@code Calendar.get(Calendar.MONTH)}.
706      */
707     @Deprecated
getMonth()708     public int getMonth() {
709         return normalize().getMonth() - 1; // adjust 1-based to 0-based
710     }
711 
712     /**
713      * Sets the month of this date to the specified value. This
714      * {@code Date} object is modified so that it represents a point
715      * in time within the specified month, with the year, date, hour,
716      * minute, and second the same as before, as interpreted in the
717      * local time zone. If the date was October 31, for example, and
718      * the month is set to June, then the new date will be treated as
719      * if it were on July 1, because June has only 30 days.
720      *
721      * @param   month   the month value between 0-11.
722      * @see     java.util.Calendar
723      * @deprecated As of JDK version 1.1,
724      * replaced by {@code Calendar.set(Calendar.MONTH, int month)}.
725      */
726     @Deprecated
setMonth(int month)727     public void setMonth(int month) {
728         int y = 0;
729         if (month >= 12) {
730             y = month / 12;
731             month %= 12;
732         } else if (month < 0) {
733             y = CalendarUtils.floorDivide(month, 12);
734             month = CalendarUtils.mod(month, 12);
735         }
736         BaseCalendar.Date d = getCalendarDate();
737         if (y != 0) {
738             d.setNormalizedYear(d.getNormalizedYear() + y);
739         }
740         d.setMonth(month + 1); // adjust 0-based to 1-based month numbering
741     }
742 
743     /**
744      * Returns the day of the month represented by this {@code Date} object.
745      * The value returned is between {@code 1} and {@code 31}
746      * representing the day of the month that contains or begins with the
747      * instant in time represented by this {@code Date} object, as
748      * interpreted in the local time zone.
749      *
750      * @return  the day of the month represented by this date.
751      * @see     java.util.Calendar
752      * @deprecated As of JDK version 1.1,
753      * replaced by {@code Calendar.get(Calendar.DAY_OF_MONTH)}.
754      */
755     @Deprecated
getDate()756     public int getDate() {
757         return normalize().getDayOfMonth();
758     }
759 
760     /**
761      * Sets the day of the month of this {@code Date} object to the
762      * specified value. This {@code Date} object is modified so that
763      * it represents a point in time within the specified day of the
764      * month, with the year, month, hour, minute, and second the same
765      * as before, as interpreted in the local time zone. If the date
766      * was April 30, for example, and the date is set to 31, then it
767      * will be treated as if it were on May 1, because April has only
768      * 30 days.
769      *
770      * @param   date   the day of the month value between 1-31.
771      * @see     java.util.Calendar
772      * @deprecated As of JDK version 1.1,
773      * replaced by {@code Calendar.set(Calendar.DAY_OF_MONTH, int date)}.
774      */
775     @Deprecated
setDate(int date)776     public void setDate(int date) {
777         getCalendarDate().setDayOfMonth(date);
778     }
779 
780     /**
781      * Returns the day of the week represented by this date. The
782      * returned value ({@code 0} = Sunday, {@code 1} = Monday,
783      * {@code 2} = Tuesday, {@code 3} = Wednesday, {@code 4} =
784      * Thursday, {@code 5} = Friday, {@code 6} = Saturday)
785      * represents the day of the week that contains or begins with
786      * the instant in time represented by this {@code Date} object,
787      * as interpreted in the local time zone.
788      *
789      * @return  the day of the week represented by this date.
790      * @see     java.util.Calendar
791      * @deprecated As of JDK version 1.1,
792      * replaced by {@code Calendar.get(Calendar.DAY_OF_WEEK)}.
793      */
794     @Deprecated
getDay()795     public int getDay() {
796         return normalize().getDayOfWeek() - BaseCalendar.SUNDAY;
797     }
798 
799     /**
800      * Returns the hour represented by this {@code Date} object. The
801      * returned value is a number ({@code 0} through {@code 23})
802      * representing the hour within the day that contains or begins
803      * with the instant in time represented by this {@code Date}
804      * object, as interpreted in the local time zone.
805      *
806      * @return  the hour represented by this date.
807      * @see     java.util.Calendar
808      * @deprecated As of JDK version 1.1,
809      * replaced by {@code Calendar.get(Calendar.HOUR_OF_DAY)}.
810      */
811     @Deprecated
getHours()812     public int getHours() {
813         return normalize().getHours();
814     }
815 
816     /**
817      * Sets the hour of this {@code Date} object to the specified value.
818      * This {@code Date} object is modified so that it represents a point
819      * in time within the specified hour of the day, with the year, month,
820      * date, minute, and second the same as before, as interpreted in the
821      * local time zone.
822      *
823      * @param   hours   the hour value.
824      * @see     java.util.Calendar
825      * @deprecated As of JDK version 1.1,
826      * replaced by {@code Calendar.set(Calendar.HOUR_OF_DAY, int hours)}.
827      */
828     @Deprecated
setHours(int hours)829     public void setHours(int hours) {
830         getCalendarDate().setHours(hours);
831     }
832 
833     /**
834      * Returns the number of minutes past the hour represented by this date,
835      * as interpreted in the local time zone.
836      * The value returned is between {@code 0} and {@code 59}.
837      *
838      * @return  the number of minutes past the hour represented by this date.
839      * @see     java.util.Calendar
840      * @deprecated As of JDK version 1.1,
841      * replaced by {@code Calendar.get(Calendar.MINUTE)}.
842      */
843     @Deprecated
getMinutes()844     public int getMinutes() {
845         return normalize().getMinutes();
846     }
847 
848     /**
849      * Sets the minutes of this {@code Date} object to the specified value.
850      * This {@code Date} object is modified so that it represents a point
851      * in time within the specified minute of the hour, with the year, month,
852      * date, hour, and second the same as before, as interpreted in the
853      * local time zone.
854      *
855      * @param   minutes   the value of the minutes.
856      * @see     java.util.Calendar
857      * @deprecated As of JDK version 1.1,
858      * replaced by {@code Calendar.set(Calendar.MINUTE, int minutes)}.
859      */
860     @Deprecated
setMinutes(int minutes)861     public void setMinutes(int minutes) {
862         getCalendarDate().setMinutes(minutes);
863     }
864 
865     /**
866      * Returns the number of seconds past the minute represented by this date.
867      * The value returned is between {@code 0} and {@code 61}. The
868      * values {@code 60} and {@code 61} can only occur on those
869      * Java Virtual Machines that take leap seconds into account.
870      *
871      * @return  the number of seconds past the minute represented by this date.
872      * @see     java.util.Calendar
873      * @deprecated As of JDK version 1.1,
874      * replaced by {@code Calendar.get(Calendar.SECOND)}.
875      */
876     @Deprecated
getSeconds()877     public int getSeconds() {
878         return normalize().getSeconds();
879     }
880 
881     /**
882      * Sets the seconds of this {@code Date} to the specified value.
883      * This {@code Date} object is modified so that it represents a
884      * point in time within the specified second of the minute, with
885      * the year, month, date, hour, and minute the same as before, as
886      * interpreted in the local time zone.
887      *
888      * @param   seconds   the seconds value.
889      * @see     java.util.Calendar
890      * @deprecated As of JDK version 1.1,
891      * replaced by {@code Calendar.set(Calendar.SECOND, int seconds)}.
892      */
893     @Deprecated
setSeconds(int seconds)894     public void setSeconds(int seconds) {
895         getCalendarDate().setSeconds(seconds);
896     }
897 
898     /**
899      * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
900      * represented by this {@code Date} object.
901      *
902      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
903      *          represented by this date.
904      */
getTime()905     public long getTime() {
906         return getTimeImpl();
907     }
908 
getTimeImpl()909     private final long getTimeImpl() {
910         if (cdate != null && !cdate.isNormalized()) {
911             normalize();
912         }
913         return fastTime;
914     }
915 
916     /**
917      * Sets this {@code Date} object to represent a point in time that is
918      * {@code time} milliseconds after January 1, 1970 00:00:00 GMT.
919      *
920      * @param   time   the number of milliseconds.
921      */
setTime(long time)922     public void setTime(long time) {
923         fastTime = time;
924         cdate = null;
925     }
926 
927     /**
928      * Tests if this date is before the specified date.
929      *
930      * @param   when   a date.
931      * @return  {@code true} if and only if the instant of time
932      *            represented by this {@code Date} object is strictly
933      *            earlier than the instant represented by {@code when};
934      *          {@code false} otherwise.
935      * @throws    NullPointerException if {@code when} is null.
936      */
before(Date when)937     public boolean before(Date when) {
938         return getMillisOf(this) < getMillisOf(when);
939     }
940 
941     /**
942      * Tests if this date is after the specified date.
943      *
944      * @param   when   a date.
945      * @return  {@code true} if and only if the instant represented
946      *          by this {@code Date} object is strictly later than the
947      *          instant represented by {@code when};
948      *          {@code false} otherwise.
949      * @throws    NullPointerException if {@code when} is null.
950      */
after(Date when)951     public boolean after(Date when) {
952         return getMillisOf(this) > getMillisOf(when);
953     }
954 
955     /**
956      * Compares two dates for equality.
957      * The result is {@code true} if and only if the argument is
958      * not {@code null} and is a {@code Date} object that
959      * represents the same point in time, to the millisecond, as this object.
960      * <p>
961      * Thus, two {@code Date} objects are equal if and only if the
962      * {@code getTime} method returns the same {@code long}
963      * value for both.
964      *
965      * @param   obj   the object to compare with.
966      * @return  {@code true} if the objects are the same;
967      *          {@code false} otherwise.
968      * @see     java.util.Date#getTime()
969      */
equals(Object obj)970     public boolean equals(Object obj) {
971         return obj instanceof Date && getTime() == ((Date) obj).getTime();
972     }
973 
974     /**
975      * Returns the millisecond value of this {@code Date} object
976      * without affecting its internal state.
977      */
getMillisOf(Date date)978     static final long getMillisOf(Date date) {
979         if (date.getClass() != Date.class) {
980             return date.getTime();
981         }
982         if (date.cdate == null || date.cdate.isNormalized()) {
983             return date.fastTime;
984         }
985         BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone();
986         return gcal.getTime(d);
987     }
988 
989     /**
990      * Compares two Dates for ordering.
991      *
992      * @param   anotherDate   the {@code Date} to be compared.
993      * @return  the value {@code 0} if the argument Date is equal to
994      *          this Date; a value less than {@code 0} if this Date
995      *          is before the Date argument; and a value greater than
996      *      {@code 0} if this Date is after the Date argument.
997      * @since   1.2
998      * @throws    NullPointerException if {@code anotherDate} is null.
999      */
1000     @Override
compareTo(Date anotherDate)1001     public int compareTo(Date anotherDate) {
1002         return Long.compare(getMillisOf(this), getMillisOf(anotherDate));
1003     }
1004 
1005     /**
1006      * Returns a hash code value for this object. The result is the
1007      * exclusive OR of the two halves of the primitive {@code long}
1008      * value returned by the {@link Date#getTime}
1009      * method. That is, the hash code is the value of the expression:
1010      * <blockquote><pre>{@code
1011      * (int)(this.getTime()^(this.getTime() >>> 32))
1012      * }</pre></blockquote>
1013      *
1014      * @return  a hash code value for this object.
1015      */
hashCode()1016     public int hashCode() {
1017         long ht = this.getTime();
1018         return (int) ht ^ (int) (ht >> 32);
1019     }
1020 
1021     /**
1022      * Converts this {@code Date} object to a {@code String}
1023      * of the form:
1024      * <blockquote><pre>
1025      * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
1026      * where:<ul>
1027      * <li>{@code dow} is the day of the week ({@code Sun, Mon, Tue, Wed,
1028      *     Thu, Fri, Sat}).
1029      * <li>{@code mon} is the month ({@code Jan, Feb, Mar, Apr, May, Jun,
1030      *     Jul, Aug, Sep, Oct, Nov, Dec}).
1031      * <li>{@code dd} is the day of the month ({@code 01} through
1032      *     {@code 31}), as two decimal digits.
1033      * <li>{@code hh} is the hour of the day ({@code 00} through
1034      *     {@code 23}), as two decimal digits.
1035      * <li>{@code mm} is the minute within the hour ({@code 00} through
1036      *     {@code 59}), as two decimal digits.
1037      * <li>{@code ss} is the second within the minute ({@code 00} through
1038      *     {@code 61}, as two decimal digits.
1039      * <li>{@code zzz} is the time zone (and may reflect daylight saving
1040      *     time). Standard time zone abbreviations include those
1041      *     recognized by the method {@code parse}. If time zone
1042      *     information is not available, then {@code zzz} is empty -
1043      *     that is, it consists of no characters at all.
1044      * <li>{@code yyyy} is the year, as four decimal digits.
1045      * </ul>
1046      *
1047      * @return  a string representation of this date.
1048      * @see     java.util.Date#toLocaleString()
1049      * @see     java.util.Date#toGMTString()
1050      */
toString()1051     public String toString() {
1052         // "EEE MMM dd HH:mm:ss zzz yyyy";
1053         BaseCalendar.Date date = normalize();
1054         StringBuilder sb = new StringBuilder(28);
1055         int index = date.getDayOfWeek();
1056         if (index == BaseCalendar.SUNDAY) {
1057             index = 8;
1058         }
1059         convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
1060         convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
1061         CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
1062 
1063         CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
1064         CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
1065         CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
1066         TimeZone zi = date.getZone();
1067         if (zi != null) {
1068             sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
1069         } else {
1070             sb.append("GMT");
1071         }
1072         sb.append(' ').append(date.getYear());  // yyyy
1073         return sb.toString();
1074     }
1075 
1076     /**
1077      * Converts the given name to its 3-letter abbreviation (e.g.,
1078      * "monday" -> "Mon") and stored the abbreviation in the given
1079      * {@code StringBuilder}.
1080      */
convertToAbbr(StringBuilder sb, String name)1081     private static final StringBuilder convertToAbbr(StringBuilder sb, String name) {
1082         sb.append(Character.toUpperCase(name.charAt(0)));
1083         sb.append(name.charAt(1)).append(name.charAt(2));
1084         return sb;
1085     }
1086 
1087     /**
1088      * Creates a string representation of this {@code Date} object in an
1089      * implementation-dependent form. The intent is that the form should
1090      * be familiar to the user of the Java application, wherever it may
1091      * happen to be running. The intent is comparable to that of the
1092      * "{@code %c}" format supported by the {@code strftime()}
1093      * function of ISO&nbsp;C.
1094      *
1095      * @return  a string representation of this date, using the locale
1096      *          conventions.
1097      * @see     java.text.DateFormat
1098      * @see     java.util.Date#toString()
1099      * @see     java.util.Date#toGMTString()
1100      * @deprecated As of JDK version 1.1,
1101      * replaced by {@code DateFormat.format(Date date)}.
1102      */
1103     @Deprecated
toLocaleString()1104     public String toLocaleString() {
1105         DateFormat formatter = DateFormat.getDateTimeInstance();
1106         return formatter.format(this);
1107     }
1108 
1109     /**
1110      * Creates a string representation of this {@code Date} object of
1111      * the form:
1112      * <blockquote><pre>
1113      * d mon yyyy hh:mm:ss GMT</pre></blockquote>
1114      * where:<ul>
1115      * <li><i>d</i> is the day of the month ({@code 1} through {@code 31}),
1116      *     as one or two decimal digits.
1117      * <li><i>mon</i> is the month ({@code Jan, Feb, Mar, Apr, May, Jun, Jul,
1118      *     Aug, Sep, Oct, Nov, Dec}).
1119      * <li><i>yyyy</i> is the year, as four decimal digits.
1120      * <li><i>hh</i> is the hour of the day ({@code 00} through {@code 23}),
1121      *     as two decimal digits.
1122      * <li><i>mm</i> is the minute within the hour ({@code 00} through
1123      *     {@code 59}), as two decimal digits.
1124      * <li><i>ss</i> is the second within the minute ({@code 00} through
1125      *     {@code 61}), as two decimal digits.
1126      * <li><i>GMT</i> is exactly the ASCII letters "{@code GMT}" to indicate
1127      *     Greenwich Mean Time.
1128      * </ul><p>
1129      * The result does not depend on the local time zone.
1130      *
1131      * @return  a string representation of this date, using the Internet GMT
1132      *          conventions.
1133      * @see     java.text.DateFormat
1134      * @see     java.util.Date#toString()
1135      * @see     java.util.Date#toLocaleString()
1136      * @deprecated As of JDK version 1.1,
1137      * replaced by {@code DateFormat.format(Date date)}, using a
1138      * GMT {@code TimeZone}.
1139      */
1140     @Deprecated
toGMTString()1141     public String toGMTString() {
1142         // d MMM yyyy HH:mm:ss 'GMT'
1143         long t = getTime();
1144         BaseCalendar cal = getCalendarSystem(t);
1145         BaseCalendar.Date date =
1146             (BaseCalendar.Date) cal.getCalendarDate(getTime(), (TimeZone)null);
1147         StringBuilder sb = new StringBuilder(32);
1148         CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 1).append(' '); // d
1149         convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
1150         sb.append(date.getYear()).append(' ');                            // yyyy
1151         CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');      // HH
1152         CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':');    // mm
1153         CalendarUtils.sprintf0d(sb, date.getSeconds(), 2);                // ss
1154         sb.append(" GMT");                                                // ' GMT'
1155         return sb.toString();
1156     }
1157 
1158     /**
1159      * Returns the offset, measured in minutes, for the local time zone
1160      * relative to UTC that is appropriate for the time represented by
1161      * this {@code Date} object.
1162      * <p>
1163      * For example, in Massachusetts, five time zones west of Greenwich:
1164      * <blockquote><pre>
1165      * new Date(96, 1, 14).getTimezoneOffset() returns 300</pre></blockquote>
1166      * because on February 14, 1996, standard time (Eastern Standard Time)
1167      * is in use, which is offset five hours from UTC; but:
1168      * <blockquote><pre>
1169      * new Date(96, 5, 1).getTimezoneOffset() returns 240</pre></blockquote>
1170      * because on June 1, 1996, daylight saving time (Eastern Daylight Time)
1171      * is in use, which is offset only four hours from UTC.<p>
1172      * This method produces the same result as if it computed:
1173      * <blockquote><pre>
1174      * (this.getTime() - UTC(this.getYear(),
1175      *                       this.getMonth(),
1176      *                       this.getDate(),
1177      *                       this.getHours(),
1178      *                       this.getMinutes(),
1179      *                       this.getSeconds())) / (60 * 1000)
1180      * </pre></blockquote>
1181      *
1182      * @return  the time-zone offset, in minutes, for the current time zone.
1183      * @see     java.util.Calendar#ZONE_OFFSET
1184      * @see     java.util.Calendar#DST_OFFSET
1185      * @see     java.util.TimeZone#getDefault
1186      * @deprecated As of JDK version 1.1,
1187      * replaced by {@code -(Calendar.get(Calendar.ZONE_OFFSET) +
1188      * Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)}.
1189      */
1190     @Deprecated
getTimezoneOffset()1191     public int getTimezoneOffset() {
1192         int zoneOffset;
1193         if (cdate == null) {
1194             // Android-changed: Android specific time zone logic
1195             GregorianCalendar cal = new GregorianCalendar(fastTime);
1196             zoneOffset = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET));
1197         } else {
1198             normalize();
1199             zoneOffset = cdate.getZoneOffset();
1200         }
1201         return -zoneOffset/60000;  // convert to minutes
1202     }
1203 
getCalendarDate()1204     private final BaseCalendar.Date getCalendarDate() {
1205         if (cdate == null) {
1206             BaseCalendar cal = getCalendarSystem(fastTime);
1207             cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime,
1208                                                             TimeZone.getDefaultRef());
1209         }
1210         return cdate;
1211     }
1212 
normalize()1213     private final BaseCalendar.Date normalize() {
1214         if (cdate == null) {
1215             BaseCalendar cal = getCalendarSystem(fastTime);
1216             cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime,
1217                                                             TimeZone.getDefaultRef());
1218             return cdate;
1219         }
1220 
1221         // Normalize cdate with the TimeZone in cdate first. This is
1222         // required for the compatible behavior.
1223         if (!cdate.isNormalized()) {
1224             cdate = normalize(cdate);
1225         }
1226 
1227         // If the default TimeZone has changed, then recalculate the
1228         // fields with the new TimeZone.
1229         TimeZone tz = TimeZone.getDefaultRef();
1230         if (tz != cdate.getZone()) {
1231             cdate.setZone(tz);
1232             CalendarSystem cal = getCalendarSystem(cdate);
1233             cal.getCalendarDate(fastTime, cdate);
1234         }
1235         return cdate;
1236     }
1237 
1238     // fastTime and the returned data are in sync upon return.
normalize(BaseCalendar.Date date)1239     private final BaseCalendar.Date normalize(BaseCalendar.Date date) {
1240         int y = date.getNormalizedYear();
1241         int m = date.getMonth();
1242         int d = date.getDayOfMonth();
1243         int hh = date.getHours();
1244         int mm = date.getMinutes();
1245         int ss = date.getSeconds();
1246         int ms = date.getMillis();
1247         TimeZone tz = date.getZone();
1248 
1249         // If the specified year can't be handled using a long value
1250         // in milliseconds, GregorianCalendar is used for full
1251         // compatibility with underflow and overflow. This is required
1252         // by some JCK tests. The limits are based max year values -
1253         // years that can be represented by max values of d, hh, mm,
1254         // ss and ms. Also, let GregorianCalendar handle the default
1255         // cutover year so that we don't need to worry about the
1256         // transition here.
1257         if (y == 1582 || y > 280000000 || y < -280000000) {
1258             if (tz == null) {
1259                 tz = TimeZone.getTimeZone("GMT");
1260             }
1261             GregorianCalendar gc = new GregorianCalendar(tz);
1262             gc.clear();
1263             gc.set(GregorianCalendar.MILLISECOND, ms);
1264             gc.set(y, m-1, d, hh, mm, ss);
1265             fastTime = gc.getTimeInMillis();
1266             BaseCalendar cal = getCalendarSystem(fastTime);
1267             date = (BaseCalendar.Date) cal.getCalendarDate(fastTime, tz);
1268             return date;
1269         }
1270 
1271         BaseCalendar cal = getCalendarSystem(y);
1272         if (cal != getCalendarSystem(date)) {
1273             date = (BaseCalendar.Date) cal.newCalendarDate(tz);
1274             date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
1275         }
1276         // Perform the GregorianCalendar-style normalization.
1277         fastTime = cal.getTime(date);
1278 
1279         // In case the normalized date requires the other calendar
1280         // system, we need to recalculate it using the other one.
1281         BaseCalendar ncal = getCalendarSystem(fastTime);
1282         if (ncal != cal) {
1283             date = (BaseCalendar.Date) ncal.newCalendarDate(tz);
1284             date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
1285             fastTime = ncal.getTime(date);
1286         }
1287         return date;
1288     }
1289 
1290     /**
1291      * Returns the Gregorian or Julian calendar system to use with the
1292      * given date. Use Gregorian from October 15, 1582.
1293      *
1294      * @param year normalized calendar year (not -1900)
1295      * @return the CalendarSystem to use for the specified date
1296      */
getCalendarSystem(int year)1297     private static final BaseCalendar getCalendarSystem(int year) {
1298         if (year >= 1582) {
1299             return gcal;
1300         }
1301         return getJulianCalendar();
1302     }
1303 
getCalendarSystem(long utc)1304     private static final BaseCalendar getCalendarSystem(long utc) {
1305         // Quickly check if the time stamp given by `utc' is the Epoch
1306         // or later. If it's before 1970, we convert the cutover to
1307         // local time to compare.
1308         if (utc >= 0
1309             || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER
1310                         - TimeZone.getDefaultRef().getOffset(utc)) {
1311             return gcal;
1312         }
1313         return getJulianCalendar();
1314     }
1315 
getCalendarSystem(BaseCalendar.Date cdate)1316     private static final BaseCalendar getCalendarSystem(BaseCalendar.Date cdate) {
1317         if (jcal == null) {
1318             return gcal;
1319         }
1320         if (cdate.getEra() != null) {
1321             return jcal;
1322         }
1323         return gcal;
1324     }
1325 
getJulianCalendar()1326     private static final synchronized BaseCalendar getJulianCalendar() {
1327         if (jcal == null) {
1328             jcal = (BaseCalendar) CalendarSystem.forName("julian");
1329         }
1330         return jcal;
1331     }
1332 
1333     /**
1334      * Save the state of this object to a stream (i.e., serialize it).
1335      *
1336      * @serialData The value returned by {@code getTime()}
1337      *             is emitted (long).  This represents the offset from
1338      *             January 1, 1970, 00:00:00 GMT in milliseconds.
1339      */
1340     @java.io.Serial
writeObject(ObjectOutputStream s)1341     private void writeObject(ObjectOutputStream s)
1342          throws IOException
1343     {
1344         s.defaultWriteObject();
1345         s.writeLong(getTimeImpl());
1346     }
1347 
1348     /**
1349      * Reconstitute this object from a stream (i.e., deserialize it).
1350      */
1351     @java.io.Serial
readObject(ObjectInputStream s)1352     private void readObject(ObjectInputStream s)
1353          throws IOException, ClassNotFoundException
1354     {
1355         s.defaultReadObject();
1356         fastTime = s.readLong();
1357     }
1358 
1359     /**
1360      * Obtains an instance of {@code Date} from an {@code Instant} object.
1361      * <p>
1362      * {@code Instant} uses a precision of nanoseconds, whereas {@code Date}
1363      * uses a precision of milliseconds.  The conversion will truncate any
1364      * excess precision information as though the amount in nanoseconds was
1365      * subject to integer division by one million.
1366      * <p>
1367      * {@code Instant} can store points on the time-line further in the future
1368      * and further in the past than {@code Date}. In this scenario, this method
1369      * will throw an exception.
1370      *
1371      * @param instant  the instant to convert
1372      * @return a {@code Date} representing the same point on the time-line as
1373      *  the provided instant
1374      * @throws    NullPointerException if {@code instant} is null.
1375      * @throws    IllegalArgumentException if the instant is too large to
1376      *  represent as a {@code Date}
1377      * @since 1.8
1378      */
from(Instant instant)1379     public static Date from(Instant instant) {
1380         try {
1381             return new Date(instant.toEpochMilli());
1382         } catch (ArithmeticException ex) {
1383             throw new IllegalArgumentException(ex);
1384         }
1385     }
1386 
1387     /**
1388      * Converts this {@code Date} object to an {@code Instant}.
1389      * <p>
1390      * The conversion creates an {@code Instant} that represents the same
1391      * point on the time-line as this {@code Date}.
1392      *
1393      * @return an instant representing the same point on the time-line as
1394      *  this {@code Date} object
1395      * @since 1.8
1396      */
toInstant()1397     public Instant toInstant() {
1398         return Instant.ofEpochMilli(getTime());
1399     }
1400 }
1401