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