KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > Date


1 /*
2  * @(#)Date.java 1.81 07/03/20
3  *
4  * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util;
9
10 import java.text.DateFormat JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.ObjectOutputStream JavaDoc;
13 import java.io.ObjectInputStream JavaDoc;
14 import java.lang.ref.SoftReference JavaDoc;
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&nbsp;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&nbsp;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&nbsp;day&nbsp;=
41  * 24&nbsp;&times;&nbsp;60&nbsp;&times;&nbsp;60&nbsp;= 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>&nbsp;<code>-&nbsp;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 1.81, 03/20/07
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 JavaDoc, Cloneable JavaDoc, Comparable JavaDoc<Date JavaDoc>
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
254     public Date(String JavaDoc s) {
255         this(parse(s));
256     }
257
258     /**
259      * Return a copy of this object.
260      */

261     public Object JavaDoc clone() {
262         Date JavaDoc d = null;
263         try {
264             d = (Date JavaDoc)super.clone();
265         if (cdate != null) {
266         d.cdate = (BaseCalendar.Date) cdate.clone();
267         }
268         } catch (CloneNotSupportedException JavaDoc 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 JavaDoc
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 JavaDoc d = new Date JavaDoc(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 JavaDoc
435     public static long parse(String JavaDoc 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 JavaDoc.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 JavaDoc();
599     }
600     private final static String JavaDoc 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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc
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 JavaDoc 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 JavaDoc 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 JavaDoc obj) {
931         return obj instanceof Date JavaDoc && getTime() == ((Date JavaDoc) 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 JavaDoc date) {
939     if (date.cdate == null) {
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 JavaDoc 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 JavaDoc toString() {
1009    // "EEE MMM dd HH:mm:ss zzz yyyy";
1010
BaseCalendar.Date date = normalize();
1011    StringBuilder JavaDoc sb = new StringBuilder JavaDoc(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 JavaDoc 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 JavaDoc convertToAbbr(StringBuilder JavaDoc sb, String JavaDoc 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&nbsp;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 JavaDoc
1061    public String JavaDoc toLocaleString() {
1062    DateFormat JavaDoc 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 JavaDoc
1098    public String JavaDoc 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 JavaDoc)null);
1104    StringBuilder JavaDoc sb = new StringBuilder JavaDoc(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 JavaDoc
1148    public int getTimezoneOffset() {
1149    int zoneOffset;
1150        if (cdate == null) {
1151        TimeZone JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc gc = new GregorianCalendar JavaDoc(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 t) {
1265    if (t >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER) {
1266        return gcal;
1267    }
1268    return getJulianCalendar();
1269    }
1270
1271    private static final BaseCalendar getCalendarSystem(BaseCalendar.Date cdate) {
1272    if (jcal == null) {
1273        return gcal;
1274    }
1275    if (cdate.getEra() != null) {
1276        return jcal;
1277    }
1278    return gcal;
1279    }
1280
1281    synchronized private static final BaseCalendar getJulianCalendar() {
1282    if (jcal == null) {
1283        jcal = (BaseCalendar) CalendarSystem.forName("julian");
1284    }
1285    return jcal;
1286    }
1287
1288    /**
1289     * Save the state of this object to a stream (i.e., serialize it).
1290     *
1291     * @serialData The value returned by <code>getTime()</code>
1292     * is emitted (long). This represents the offset from
1293     * January 1, 1970, 00:00:00 GMT in milliseconds.
1294     */

1295    private void writeObject(ObjectOutputStream JavaDoc s)
1296         throws IOException JavaDoc
1297    {
1298        s.writeLong(getTimeImpl());
1299    }
1300
1301    /**
1302     * Reconstitute this object from a stream (i.e., deserialize it).
1303     */

1304    private void readObject(ObjectInputStream JavaDoc s)
1305         throws IOException JavaDoc, ClassNotFoundException JavaDoc
1306    {
1307        fastTime = s.readLong();
1308    }
1309}
1310
Popular Tags