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