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