0001 /*
0002 * Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.util;
0027
0028 import java.text.DateFormat;
0029 import java.io.IOException;
0030 import java.io.ObjectOutputStream;
0031 import java.io.ObjectInputStream;
0032 import java.lang.ref.SoftReference;
0033 import sun.util.calendar.BaseCalendar;
0034 import sun.util.calendar.CalendarDate;
0035 import sun.util.calendar.CalendarSystem;
0036 import sun.util.calendar.CalendarUtils;
0037 import sun.util.calendar.Era;
0038 import sun.util.calendar.Gregorian;
0039 import sun.util.calendar.ZoneInfo;
0040
0041 /**
0042 * The class <code>Date</code> represents a specific instant
0043 * in time, with millisecond precision.
0044 * <p>
0045 * Prior to JDK 1.1, the class <code>Date</code> had two additional
0046 * functions. It allowed the interpretation of dates as year, month, day, hour,
0047 * minute, and second values. It also allowed the formatting and parsing
0048 * of date strings. Unfortunately, the API for these functions was not
0049 * amenable to internationalization. As of JDK 1.1, the
0050 * <code>Calendar</code> class should be used to convert between dates and time
0051 * fields and the <code>DateFormat</code> class should be used to format and
0052 * parse date strings.
0053 * The corresponding methods in <code>Date</code> are deprecated.
0054 * <p>
0055 * Although the <code>Date</code> class is intended to reflect
0056 * coordinated universal time (UTC), it may not do so exactly,
0057 * depending on the host environment of the Java Virtual Machine.
0058 * Nearly all modern operating systems assume that 1 day =
0059 * 24 × 60 × 60 = 86400 seconds
0060 * in all cases. In UTC, however, about once every year or two there
0061 * is an extra second, called a "leap second." The leap
0062 * second is always added as the last second of the day, and always
0063 * on December 31 or June 30. For example, the last minute of the
0064 * year 1995 was 61 seconds long, thanks to an added leap second.
0065 * Most computer clocks are not accurate enough to be able to reflect
0066 * the leap-second distinction.
0067 * <p>
0068 * Some computer standards are defined in terms of Greenwich mean
0069 * time (GMT), which is equivalent to universal time (UT). GMT is
0070 * the "civil" name for the standard; UT is the
0071 * "scientific" name for the same standard. The
0072 * distinction between UTC and UT is that UTC is based on an atomic
0073 * clock and UT is based on astronomical observations, which for all
0074 * practical purposes is an invisibly fine hair to split. Because the
0075 * earth's rotation is not uniform (it slows down and speeds up
0076 * in complicated ways), UT does not always flow uniformly. Leap
0077 * seconds are introduced as needed into UTC so as to keep UTC within
0078 * 0.9 seconds of UT1, which is a version of UT with certain
0079 * corrections applied. There are other time and date systems as
0080 * well; for example, the time scale used by the satellite-based
0081 * global positioning system (GPS) is synchronized to UTC but is
0082 * <i>not</i> adjusted for leap seconds. An interesting source of
0083 * further information is the U.S. Naval Observatory, particularly
0084 * the Directorate of Time at:
0085 * <blockquote><pre>
0086 * <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a>
0087 * </pre></blockquote>
0088 * <p>
0089 * and their definitions of "Systems of Time" at:
0090 * <blockquote><pre>
0091 * <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a>
0092 * </pre></blockquote>
0093 * <p>
0094 * In all methods of class <code>Date</code> that accept or return
0095 * year, month, date, hours, minutes, and seconds values, the
0096 * following representations are used:
0097 * <ul>
0098 * <li>A year <i>y</i> is represented by the integer
0099 * <i>y</i> <code>- 1900</code>.
0100 * <li>A month is represented by an integer from 0 to 11; 0 is January,
0101 * 1 is February, and so forth; thus 11 is December.
0102 * <li>A date (day of month) is represented by an integer from 1 to 31
0103 * in the usual manner.
0104 * <li>An hour is represented by an integer from 0 to 23. Thus, the hour
0105 * from midnight to 1 a.m. is hour 0, and the hour from noon to 1
0106 * p.m. is hour 12.
0107 * <li>A minute is represented by an integer from 0 to 59 in the usual manner.
0108 * <li>A second is represented by an integer from 0 to 61; the values 60 and
0109 * 61 occur only for leap seconds and even then only in Java
0110 * implementations that actually track leap seconds correctly. Because
0111 * of the manner in which leap seconds are currently introduced, it is
0112 * extremely unlikely that two leap seconds will occur in the same
0113 * minute, but this specification follows the date and time conventions
0114 * for ISO C.
0115 * </ul>
0116 * <p>
0117 * In all cases, arguments given to methods for these purposes need
0118 * not fall within the indicated ranges; for example, a date may be
0119 * specified as January 32 and is interpreted as meaning February 1.
0120 *
0121 * @author James Gosling
0122 * @author Arthur van Hoff
0123 * @author Alan Liu
0124 * @version 1.90, 05/05/07
0125 * @see java.text.DateFormat
0126 * @see java.util.Calendar
0127 * @see java.util.TimeZone
0128 * @since JDK1.0
0129 */
0130 public class Date implements java.io.Serializable, Cloneable,
0131 Comparable<Date> {
0132 private static final BaseCalendar gcal = CalendarSystem
0133 .getGregorianCalendar();
0134 private static BaseCalendar jcal;
0135
0136 private transient long fastTime;
0137
0138 /*
0139 * If cdate is null, then fastTime indicates the time in millis.
0140 * If cdate.isNormalized() is true, then fastTime and cdate are in
0141 * synch. Otherwise, fastTime is ignored, and cdate indicates the
0142 * time.
0143 */
0144 private transient BaseCalendar.Date cdate;
0145
0146 // Initialized just before the value is used. See parse().
0147 private static int defaultCenturyStart;
0148
0149 /* use serialVersionUID from modified java.util.Date for
0150 * interoperability with JDK1.1. The Date was modified to write
0151 * and read only the UTC time.
0152 */
0153 private static final long serialVersionUID = 7523967970034938905L;
0154
0155 /**
0156 * Allocates a <code>Date</code> object and initializes it so that
0157 * it represents the time at which it was allocated, measured to the
0158 * nearest millisecond.
0159 *
0160 * @see java.lang.System#currentTimeMillis()
0161 */
0162 public Date() {
0163 this (System.currentTimeMillis());
0164 }
0165
0166 /**
0167 * Allocates a <code>Date</code> object and initializes it to
0168 * represent the specified number of milliseconds since the
0169 * standard base time known as "the epoch", namely January 1,
0170 * 1970, 00:00:00 GMT.
0171 *
0172 * @param date the milliseconds since January 1, 1970, 00:00:00 GMT.
0173 * @see java.lang.System#currentTimeMillis()
0174 */
0175 public Date(long date) {
0176 fastTime = date;
0177 }
0178
0179 /**
0180 * Allocates a <code>Date</code> object and initializes it so that
0181 * it represents midnight, local time, at the beginning of the day
0182 * specified by the <code>year</code>, <code>month</code>, and
0183 * <code>date</code> arguments.
0184 *
0185 * @param year the year minus 1900.
0186 * @param month the month between 0-11.
0187 * @param date the day of the month between 1-31.
0188 * @see java.util.Calendar
0189 * @deprecated As of JDK version 1.1,
0190 * replaced by <code>Calendar.set(year + 1900, month, date)</code>
0191 * or <code>GregorianCalendar(year + 1900, month, date)</code>.
0192 */
0193 @Deprecated
0194 public Date(int year, int month, int date) {
0195 this (year, month, date, 0, 0, 0);
0196 }
0197
0198 /**
0199 * Allocates a <code>Date</code> object and initializes it so that
0200 * it represents the instant at the start of the minute specified by
0201 * the <code>year</code>, <code>month</code>, <code>date</code>,
0202 * <code>hrs</code>, and <code>min</code> arguments, in the local
0203 * time zone.
0204 *
0205 * @param year the year minus 1900.
0206 * @param month the month between 0-11.
0207 * @param date the day of the month between 1-31.
0208 * @param hrs the hours between 0-23.
0209 * @param min the minutes between 0-59.
0210 * @see java.util.Calendar
0211 * @deprecated As of JDK version 1.1,
0212 * replaced by <code>Calendar.set(year + 1900, month, date,
0213 * hrs, min)</code> or <code>GregorianCalendar(year + 1900,
0214 * month, date, hrs, min)</code>.
0215 */
0216 @Deprecated
0217 public Date(int year, int month, int date, int hrs, int min) {
0218 this (year, month, date, hrs, min, 0);
0219 }
0220
0221 /**
0222 * Allocates a <code>Date</code> object and initializes it so that
0223 * it represents the instant at the start of the second specified
0224 * by the <code>year</code>, <code>month</code>, <code>date</code>,
0225 * <code>hrs</code>, <code>min</code>, and <code>sec</code> arguments,
0226 * in the local time zone.
0227 *
0228 * @param year the year minus 1900.
0229 * @param month the month between 0-11.
0230 * @param date the day of the month between 1-31.
0231 * @param hrs the hours between 0-23.
0232 * @param min the minutes between 0-59.
0233 * @param sec the seconds between 0-59.
0234 * @see java.util.Calendar
0235 * @deprecated As of JDK version 1.1,
0236 * replaced by <code>Calendar.set(year + 1900, month, date,
0237 * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
0238 * month, date, hrs, min, sec)</code>.
0239 */
0240 @Deprecated
0241 public Date(int year, int month, int date, int hrs, int min, int sec) {
0242 int y = year + 1900;
0243 // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
0244 if (month >= 12) {
0245 y += month / 12;
0246 month %= 12;
0247 } else if (month < 0) {
0248 y += CalendarUtils.floorDivide(month, 12);
0249 month = CalendarUtils.mod(month, 12);
0250 }
0251 BaseCalendar cal = getCalendarSystem(y);
0252 cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone
0253 .getDefaultRef());
0254 cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs,
0255 min, sec, 0);
0256 getTimeImpl();
0257 cdate = null;
0258 }
0259
0260 /**
0261 * Allocates a <code>Date</code> object and initializes it so that
0262 * it represents the date and time indicated by the string
0263 * <code>s</code>, which is interpreted as if by the
0264 * {@link Date#parse} method.
0265 *
0266 * @param s a string representation of the date.
0267 * @see java.text.DateFormat
0268 * @see java.util.Date#parse(java.lang.String)
0269 * @deprecated As of JDK version 1.1,
0270 * replaced by <code>DateFormat.parse(String s)</code>.
0271 */
0272 @Deprecated
0273 public Date(String s) {
0274 this (parse(s));
0275 }
0276
0277 /**
0278 * Return a copy of this object.
0279 */
0280 public Object clone() {
0281 Date d = null;
0282 try {
0283 d = (Date) super .clone();
0284 if (cdate != null) {
0285 d.cdate = (BaseCalendar.Date) cdate.clone();
0286 }
0287 } catch (CloneNotSupportedException e) {
0288 } // Won't happen
0289 return d;
0290 }
0291
0292 /**
0293 * Determines the date and time based on the arguments. The
0294 * arguments are interpreted as a year, month, day of the month,
0295 * hour of the day, minute within the hour, and second within the
0296 * minute, exactly as for the <tt>Date</tt> constructor with six
0297 * arguments, except that the arguments are interpreted relative
0298 * to UTC rather than to the local time zone. The time indicated is
0299 * returned represented as the distance, measured in milliseconds,
0300 * of that time from the epoch (00:00:00 GMT on January 1, 1970).
0301 *
0302 * @param year the year minus 1900.
0303 * @param month the month between 0-11.
0304 * @param date the day of the month between 1-31.
0305 * @param hrs the hours between 0-23.
0306 * @param min the minutes between 0-59.
0307 * @param sec the seconds between 0-59.
0308 * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT for
0309 * the date and time specified by the arguments.
0310 * @see java.util.Calendar
0311 * @deprecated As of JDK version 1.1,
0312 * replaced by <code>Calendar.set(year + 1900, month, date,
0313 * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
0314 * month, date, hrs, min, sec)</code>, using a UTC
0315 * <code>TimeZone</code>, followed by <code>Calendar.getTime().getTime()</code>.
0316 */
0317 @Deprecated
0318 public static long UTC(int year, int month, int date, int hrs,
0319 int min, int sec) {
0320 int y = year + 1900;
0321 // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
0322 if (month >= 12) {
0323 y += month / 12;
0324 month %= 12;
0325 } else if (month < 0) {
0326 y += CalendarUtils.floorDivide(month, 12);
0327 month = CalendarUtils.mod(month, 12);
0328 }
0329 int m = month + 1;
0330 BaseCalendar cal = getCalendarSystem(y);
0331 BaseCalendar.Date udate = (BaseCalendar.Date) cal
0332 .newCalendarDate(null);
0333 udate.setNormalizedDate(y, m, date).setTimeOfDay(hrs, min, sec,
0334 0);
0335
0336 // Use a Date instance to perform normalization. Its fastTime
0337 // is the UTC value after the normalization.
0338 Date d = new Date(0);
0339 d.normalize(udate);
0340 return d.fastTime;
0341 }
0342
0343 /**
0344 * Attempts to interpret the string <tt>s</tt> as a representation
0345 * of a date and time. If the attempt is successful, the time
0346 * indicated is returned represented as the distance, measured in
0347 * milliseconds, of that time from the epoch (00:00:00 GMT on
0348 * January 1, 1970). If the attempt fails, an
0349 * <tt>IllegalArgumentException</tt> is thrown.
0350 * <p>
0351 * It accepts many syntaxes; in particular, it recognizes the IETF
0352 * standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also
0353 * understands the continental U.S. time-zone abbreviations, but for
0354 * general use, a time-zone offset should be used: "Sat, 12 Aug 1995
0355 * 13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich
0356 * meridian). If no time zone is specified, the local time zone is
0357 * assumed. GMT and UTC are considered equivalent.
0358 * <p>
0359 * The string <tt>s</tt> is processed from left to right, looking for
0360 * data of interest. Any material in <tt>s</tt> that is within the
0361 * ASCII parenthesis characters <tt>(</tt> and <tt>)</tt> is ignored.
0362 * Parentheses may be nested. Otherwise, the only characters permitted
0363 * within <tt>s</tt> are these ASCII characters:
0364 * <blockquote><pre>
0365 * abcdefghijklmnopqrstuvwxyz
0366 * ABCDEFGHIJKLMNOPQRSTUVWXYZ
0367 * 0123456789,+-:/</pre></blockquote>
0368 * and whitespace characters.<p>
0369 * A consecutive sequence of decimal digits is treated as a decimal
0370 * number:<ul>
0371 * <li>If a number is preceded by <tt>+</tt> or <tt>-</tt> and a year
0372 * has already been recognized, then the number is a time-zone
0373 * offset. If the number is less than 24, it is an offset measured
0374 * in hours. Otherwise, it is regarded as an offset in minutes,
0375 * expressed in 24-hour time format without punctuation. A
0376 * preceding <tt>-</tt> means a westward offset. Time zone offsets
0377 * are always relative to UTC (Greenwich). Thus, for example,
0378 * <tt>-5</tt> occurring in the string would mean "five hours west
0379 * of Greenwich" and <tt>+0430</tt> would mean "four hours and
0380 * thirty minutes east of Greenwich." It is permitted for the
0381 * string to specify <tt>GMT</tt>, <tt>UT</tt>, or <tt>UTC</tt>
0382 * redundantly-for example, <tt>GMT-5</tt> or <tt>utc+0430</tt>.
0383 * <li>The number is regarded as a year number if one of the
0384 * following conditions is true:
0385 * <ul>
0386 * <li>The number is equal to or greater than 70 and followed by a
0387 * space, comma, slash, or end of string
0388 * <li>The number is less than 70, and both a month and a day of
0389 * the month have already been recognized</li>
0390 * </ul>
0391 * If the recognized year number is less than 100, it is
0392 * interpreted as an abbreviated year relative to a century of
0393 * which dates are within 80 years before and 19 years after
0394 * the time when the Date class is initialized.
0395 * After adjusting the year number, 1900 is subtracted from
0396 * it. For example, if the current year is 1999 then years in
0397 * the range 19 to 99 are assumed to mean 1919 to 1999, while
0398 * years from 0 to 18 are assumed to mean 2000 to 2018. Note
0399 * that this is slightly different from the interpretation of
0400 * years less than 100 that is used in {@link java.text.SimpleDateFormat}.
0401 * <li>If the number is followed by a colon, it is regarded as an hour,
0402 * unless an hour has already been recognized, in which case it is
0403 * regarded as a minute.
0404 * <li>If the number is followed by a slash, it is regarded as a month
0405 * (it is decreased by 1 to produce a number in the range <tt>0</tt>
0406 * to <tt>11</tt>), unless a month has already been recognized, in
0407 * which case it is regarded as a day of the month.
0408 * <li>If the number is followed by whitespace, a comma, a hyphen, or
0409 * end of string, then if an hour has been recognized but not a
0410 * minute, it is regarded as a minute; otherwise, if a minute has
0411 * been recognized but not a second, it is regarded as a second;
0412 * otherwise, it is regarded as a day of the month. </ul><p>
0413 * A consecutive sequence of letters is regarded as a word and treated
0414 * as follows:<ul>
0415 * <li>A word that matches <tt>AM</tt>, ignoring case, is ignored (but
0416 * the parse fails if an hour has not been recognized or is less
0417 * than <tt>1</tt> or greater than <tt>12</tt>).
0418 * <li>A word that matches <tt>PM</tt>, ignoring case, adds <tt>12</tt>
0419 * to the hour (but the parse fails if an hour has not been
0420 * recognized or is less than <tt>1</tt> or greater than <tt>12</tt>).
0421 * <li>Any word that matches any prefix of <tt>SUNDAY, MONDAY, TUESDAY,
0422 * WEDNESDAY, THURSDAY, FRIDAY</tt>, or <tt>SATURDAY</tt>, ignoring
0423 * case, is ignored. For example, <tt>sat, Friday, TUE</tt>, and
0424 * <tt>Thurs</tt> are ignored.
0425 * <li>Otherwise, any word that matches any prefix of <tt>JANUARY,
0426 * FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,
0427 * OCTOBER, NOVEMBER</tt>, or <tt>DECEMBER</tt>, ignoring case, and
0428 * considering them in the order given here, is recognized as
0429 * specifying a month and is converted to a number (<tt>0</tt> to
0430 * <tt>11</tt>). For example, <tt>aug, Sept, april</tt>, and
0431 * <tt>NOV</tt> are recognized as months. So is <tt>Ma</tt>, which
0432 * is recognized as <tt>MARCH</tt>, not <tt>MAY</tt>.
0433 * <li>Any word that matches <tt>GMT, UT</tt>, or <tt>UTC</tt>, ignoring
0434 * case, is treated as referring to UTC.
0435 * <li>Any word that matches <tt>EST, CST, MST</tt>, or <tt>PST</tt>,
0436 * ignoring case, is recognized as referring to the time zone in
0437 * North America that is five, six, seven, or eight hours west of
0438 * Greenwich, respectively. Any word that matches <tt>EDT, CDT,
0439 * MDT</tt>, or <tt>PDT</tt>, ignoring case, is recognized as
0440 * referring to the same time zone, respectively, during daylight
0441 * saving time.</ul><p>
0442 * Once the entire string s has been scanned, it is converted to a time
0443 * result in one of two ways. If a time zone or time-zone offset has been
0444 * recognized, then the year, month, day of month, hour, minute, and
0445 * second are interpreted in UTC and then the time-zone offset is
0446 * applied. Otherwise, the year, month, day of month, hour, minute, and
0447 * second are interpreted in the local time zone.
0448 *
0449 * @param s a string to be parsed as a date.
0450 * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
0451 * represented by the string argument.
0452 * @see java.text.DateFormat
0453 * @deprecated As of JDK version 1.1,
0454 * replaced by <code>DateFormat.parse(String s)</code>.
0455 */
0456 @Deprecated
0457 public static long parse(String s) {
0458 int year = Integer.MIN_VALUE;
0459 int mon = -1;
0460 int mday = -1;
0461 int hour = -1;
0462 int min = -1;
0463 int sec = -1;
0464 int millis = -1;
0465 int c = -1;
0466 int i = 0;
0467 int n = -1;
0468 int wst = -1;
0469 int tzoffset = -1;
0470 int prevc = 0;
0471 syntax: {
0472 if (s == null)
0473 break syntax;
0474 int limit = s.length();
0475 while (i < limit) {
0476 c = s.charAt(i);
0477 i++;
0478 if (c <= ' ' || c == ',')
0479 continue;
0480 if (c == '(') { // skip comments
0481 int depth = 1;
0482 while (i < limit) {
0483 c = s.charAt(i);
0484 i++;
0485 if (c == '(')
0486 depth++;
0487 else if (c == ')')
0488 if (--depth <= 0)
0489 break;
0490 }
0491 continue;
0492 }
0493 if ('0' <= c && c <= '9') {
0494 n = c - '0';
0495 while (i < limit && '0' <= (c = s.charAt(i))
0496 && c <= '9') {
0497 n = n * 10 + c - '0';
0498 i++;
0499 }
0500 if (prevc == '+' || prevc == '-'
0501 && year != Integer.MIN_VALUE) {
0502 // timezone offset
0503 if (n < 24)
0504 n = n * 60; // EG. "GMT-3"
0505 else
0506 n = n % 100 + n / 100 * 60; // eg "GMT-0430"
0507 if (prevc == '+') // plus means east of GMT
0508 n = -n;
0509 if (tzoffset != 0 && tzoffset != -1)
0510 break syntax;
0511 tzoffset = n;
0512 } else if (n >= 70)
0513 if (year != Integer.MIN_VALUE)
0514 break syntax;
0515 else if (c <= ' ' || c == ',' || c == '/'
0516 || i >= limit)
0517 // year = n < 1900 ? n : n - 1900;
0518 year = n;
0519 else
0520 break syntax;
0521 else if (c == ':')
0522 if (hour < 0)
0523 hour = (byte) n;
0524 else if (min < 0)
0525 min = (byte) n;
0526 else
0527 break syntax;
0528 else if (c == '/')
0529 if (mon < 0)
0530 mon = (byte) (n - 1);
0531 else if (mday < 0)
0532 mday = (byte) n;
0533 else
0534 break syntax;
0535 else if (i < limit && c != ',' && c > ' '
0536 && c != '-')
0537 break syntax;
0538 else if (hour >= 0 && min < 0)
0539 min = (byte) n;
0540 else if (min >= 0 && sec < 0)
0541 sec = (byte) n;
0542 else if (mday < 0)
0543 mday = (byte) n;
0544 // Handle two-digit years < 70 (70-99 handled above).
0545 else if (year == Integer.MIN_VALUE && mon >= 0
0546 && mday >= 0)
0547 year = n;
0548 else
0549 break syntax;
0550 prevc = 0;
0551 } else if (c == '/' || c == ':' || c == '+' || c == '-')
0552 prevc = c;
0553 else {
0554 int st = i - 1;
0555 while (i < limit) {
0556 c = s.charAt(i);
0557 if (!('A' <= c && c <= 'Z' || 'a' <= c
0558 && c <= 'z'))
0559 break;
0560 i++;
0561 }
0562 if (i <= st + 1)
0563 break syntax;
0564 int k;
0565 for (k = wtb.length; --k >= 0;)
0566 if (wtb[k]
0567 .regionMatches(true, 0, s, st, i - st)) {
0568 int action = ttb[k];
0569 if (action != 0) {
0570 if (action == 1) { // pm
0571 if (hour > 12 || hour < 1)
0572 break syntax;
0573 else if (hour < 12)
0574 hour += 12;
0575 } else if (action == 14) { // am
0576 if (hour > 12 || hour < 1)
0577 break syntax;
0578 else if (hour == 12)
0579 hour = 0;
0580 } else if (action <= 13) { // month!
0581 if (mon < 0)
0582 mon = (byte) (action - 2);
0583 else
0584 break syntax;
0585 } else {
0586 tzoffset = action - 10000;
0587 }
0588 }
0589 break;
0590 }
0591 if (k < 0)
0592 break syntax;
0593 prevc = 0;
0594 }
0595 }
0596 if (year == Integer.MIN_VALUE || mon < 0 || mday < 0)
0597 break syntax;
0598 // Parse 2-digit years within the correct default century.
0599 if (year < 100) {
0600 synchronized (Date.class) {
0601 if (defaultCenturyStart == 0) {
0602 defaultCenturyStart = gcal.getCalendarDate()
0603 .getYear() - 80;
0604 }
0605 }
0606 year += (defaultCenturyStart / 100) * 100;
0607 if (year < defaultCenturyStart)
0608 year += 100;
0609 }
0610 if (sec < 0)
0611 sec = 0;
0612 if (min < 0)
0613 min = 0;
0614 if (hour < 0)
0615 hour = 0;
0616 BaseCalendar cal = getCalendarSystem(year);
0617 if (tzoffset == -1) { // no time zone specified, have to use local
0618 BaseCalendar.Date ldate = (BaseCalendar.Date) cal
0619 .newCalendarDate(TimeZone.getDefaultRef());
0620 ldate.setDate(year, mon + 1, mday);
0621 ldate.setTimeOfDay(hour, min, sec, 0);
0622 return cal.getTime(ldate);
0623 }
0624 BaseCalendar.Date udate = (BaseCalendar.Date) cal
0625 .newCalendarDate(null); // no time zone
0626 udate.setDate(year, mon + 1, mday);
0627 udate.setTimeOfDay(hour, min, sec, 0);
0628 return cal.getTime(udate) + tzoffset * (60 * 1000);
0629 }
0630 // syntax error
0631 throw new IllegalArgumentException();
0632 }
0633
0634 private final static String wtb[] = { "am", "pm", "monday",
0635 "tuesday", "wednesday", "thursday", "friday", "saturday",
0636 "sunday", "january", "february", "march", "april", "may",
0637 "june", "july", "august", "september", "october",
0638 "november", "december", "gmt", "ut", "utc", "est", "edt",
0639 "cst", "cdt", "mst", "mdt", "pst", "pdt" };
0640 private final static int ttb[] = { 14, 1, 0, 0, 0, 0, 0, 0, 0, 2,
0641 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 10000 + 0, 10000 + 0,
0642 10000 + 0, // GMT/UT/UTC
0643 10000 + 5 * 60, 10000 + 4 * 60, // EST/EDT
0644 10000 + 6 * 60, 10000 + 5 * 60, // CST/CDT
0645 10000 + 7 * 60, 10000 + 6 * 60, // MST/MDT
0646 10000 + 8 * 60, 10000 + 7 * 60 // PST/PDT
0647 };
0648
0649 /**
0650 * Returns a value that is the result of subtracting 1900 from the
0651 * year that contains or begins with the instant in time represented
0652 * by this <code>Date</code> object, as interpreted in the local
0653 * time zone.
0654 *
0655 * @return the year represented by this date, minus 1900.
0656 * @see java.util.Calendar
0657 * @deprecated As of JDK version 1.1,
0658 * replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>.
0659 */
0660 @Deprecated
0661 public int getYear() {
0662 return normalize().getYear() - 1900;
0663 }
0664
0665 /**
0666 * Sets the year of this <tt>Date</tt> object to be the specified
0667 * value plus 1900. This <code>Date</code> object is modified so
0668 * that it represents a point in time within the specified year,
0669 * with the month, date, hour, minute, and second the same as
0670 * before, as interpreted in the local time zone. (Of course, if
0671 * the date was February 29, for example, and the year is set to a
0672 * non-leap year, then the new date will be treated as if it were
0673 * on March 1.)
0674 *
0675 * @param year the year value.
0676 * @see java.util.Calendar
0677 * @deprecated As of JDK version 1.1,
0678 * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>.
0679 */
0680 @Deprecated
0681 public void setYear(int year) {
0682 getCalendarDate().setNormalizedYear(year + 1900);
0683 }
0684
0685 /**
0686 * Returns a number representing the month that contains or begins
0687 * with the instant in time represented by this <tt>Date</tt> object.
0688 * The value returned is between <code>0</code> and <code>11</code>,
0689 * with the value <code>0</code> representing January.
0690 *
0691 * @return the month represented by this date.
0692 * @see java.util.Calendar
0693 * @deprecated As of JDK version 1.1,
0694 * replaced by <code>Calendar.get(Calendar.MONTH)</code>.
0695 */
0696 @Deprecated
0697 public int getMonth() {
0698 return normalize().getMonth() - 1; // adjust 1-based to 0-based
0699 }
0700
0701 /**
0702 * Sets the month of this date to the specified value. This
0703 * <tt>Date</tt> object is modified so that it represents a point
0704 * in time within the specified month, with the year, date, hour,
0705 * minute, and second the same as before, as interpreted in the
0706 * local time zone. If the date was October 31, for example, and
0707 * the month is set to June, then the new date will be treated as
0708 * if it were on July 1, because June has only 30 days.
0709 *
0710 * @param month the month value between 0-11.
0711 * @see java.util.Calendar
0712 * @deprecated As of JDK version 1.1,
0713 * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>.
0714 */
0715 @Deprecated
0716 public void setMonth(int month) {
0717 int y = 0;
0718 if (month >= 12) {
0719 y = month / 12;
0720 month %= 12;
0721 } else if (month < 0) {
0722 y = CalendarUtils.floorDivide(month, 12);
0723 month = CalendarUtils.mod(month, 12);
0724 }
0725 BaseCalendar.Date d = getCalendarDate();
0726 if (y != 0) {
0727 d.setNormalizedYear(d.getNormalizedYear() + y);
0728 }
0729 d.setMonth(month + 1); // adjust 0-based to 1-based month numbering
0730 }
0731
0732 /**
0733 * Returns the day of the month represented by this <tt>Date</tt> object.
0734 * The value returned is between <code>1</code> and <code>31</code>
0735 * representing the day of the month that contains or begins with the
0736 * instant in time represented by this <tt>Date</tt> object, as
0737 * interpreted in the local time zone.
0738 *
0739 * @return the day of the month represented by this date.
0740 * @see java.util.Calendar
0741 * @deprecated As of JDK version 1.1,
0742 * replaced by <code>Calendar.get(Calendar.DAY_OF_MONTH)</code>.
0743 * @deprecated
0744 */
0745 @Deprecated
0746 public int getDate() {
0747 return normalize().getDayOfMonth();
0748 }
0749
0750 /**
0751 * Sets the day of the month of this <tt>Date</tt> object to the
0752 * specified value. This <tt>Date</tt> object is modified so that
0753 * it represents a point in time within the specified day of the
0754 * month, with the year, month, hour, minute, and second the same
0755 * as before, as interpreted in the local time zone. If the date
0756 * was April 30, for example, and the date is set to 31, then it
0757 * will be treated as if it were on May 1, because April has only
0758 * 30 days.
0759 *
0760 * @param date the day of the month value between 1-31.
0761 * @see java.util.Calendar
0762 * @deprecated As of JDK version 1.1,
0763 * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>.
0764 */
0765 @Deprecated
0766 public void setDate(int date) {
0767 getCalendarDate().setDayOfMonth(date);
0768 }
0769
0770 /**
0771 * Returns the day of the week represented by this date. The
0772 * returned value (<tt>0</tt> = Sunday, <tt>1</tt> = Monday,
0773 * <tt>2</tt> = Tuesday, <tt>3</tt> = Wednesday, <tt>4</tt> =
0774 * Thursday, <tt>5</tt> = Friday, <tt>6</tt> = Saturday)
0775 * represents the day of the week that contains or begins with
0776 * the instant in time represented by this <tt>Date</tt> object,
0777 * as interpreted in the local time zone.
0778 *
0779 * @return the day of the week represented by this date.
0780 * @see java.util.Calendar
0781 * @deprecated As of JDK version 1.1,
0782 * replaced by <code>Calendar.get(Calendar.DAY_OF_WEEK)</code>.
0783 */
0784 @Deprecated
0785 public int getDay() {
0786 return normalize().getDayOfWeek() - gcal.SUNDAY;
0787 }
0788
0789 /**
0790 * Returns the hour represented by this <tt>Date</tt> object. The
0791 * returned value is a number (<tt>0</tt> through <tt>23</tt>)
0792 * representing the hour within the day that contains or begins
0793 * with the instant in time represented by this <tt>Date</tt>
0794 * object, as interpreted in the local time zone.
0795 *
0796 * @return the hour represented by this date.
0797 * @see java.util.Calendar
0798 * @deprecated As of JDK version 1.1,
0799 * replaced by <code>Calendar.get(Calendar.HOUR_OF_DAY)</code>.
0800 */
0801 @Deprecated
0802 public int getHours() {
0803 return normalize().getHours();
0804 }
0805
0806 /**
0807 * Sets the hour of this <tt>Date</tt> object to the specified value.
0808 * This <tt>Date</tt> object is modified so that it represents a point
0809 * in time within the specified hour of the day, with the year, month,
0810 * date, minute, and second the same as before, as interpreted in the
0811 * local time zone.
0812 *
0813 * @param hours the hour value.
0814 * @see java.util.Calendar
0815 * @deprecated As of JDK version 1.1,
0816 * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>.
0817 */
0818 @Deprecated
0819 public void setHours(int hours) {
0820 getCalendarDate().setHours(hours);
0821 }
0822
0823 /**
0824 * Returns the number of minutes past the hour represented by this date,
0825 * as interpreted in the local time zone.
0826 * The value returned is between <code>0</code> and <code>59</code>.
0827 *
0828 * @return the number of minutes past the hour represented by this date.
0829 * @see java.util.Calendar
0830 * @deprecated As of JDK version 1.1,
0831 * replaced by <code>Calendar.get(Calendar.MINUTE)</code>.
0832 */
0833 @Deprecated
0834 public int getMinutes() {
0835 return normalize().getMinutes();
0836 }
0837
0838 /**
0839 * Sets the minutes of this <tt>Date</tt> object to the specified value.
0840 * This <tt>Date</tt> object is modified so that it represents a point
0841 * in time within the specified minute of the hour, with the year, month,
0842 * date, hour, and second the same as before, as interpreted in the
0843 * local time zone.
0844 *
0845 * @param minutes the value of the minutes.
0846 * @see java.util.Calendar
0847 * @deprecated As of JDK version 1.1,
0848 * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>.
0849 */
0850 @Deprecated
0851 public void setMinutes(int minutes) {
0852 getCalendarDate().setMinutes(minutes);
0853 }
0854
0855 /**
0856 * Returns the number of seconds past the minute represented by this date.
0857 * The value returned is between <code>0</code> and <code>61</code>. The
0858 * values <code>60</code> and <code>61</code> can only occur on those
0859 * Java Virtual Machines that take leap seconds into account.
0860 *
0861 * @return the number of seconds past the minute represented by this date.
0862 * @see java.util.Calendar
0863 * @deprecated As of JDK version 1.1,
0864 * replaced by <code>Calendar.get(Calendar.SECOND)</code>.
0865 */
0866 @Deprecated
0867 public int getSeconds() {
0868 return normalize().getSeconds();
0869 }
0870
0871 /**
0872 * Sets the seconds of this <tt>Date</tt> to the specified value.
0873 * This <tt>Date</tt> object is modified so that it represents a
0874 * point in time within the specified second of the minute, with
0875 * the year, month, date, hour, and minute the same as before, as
0876 * interpreted in the local time zone.
0877 *
0878 * @param seconds the seconds value.
0879 * @see java.util.Calendar
0880 * @deprecated As of JDK version 1.1,
0881 * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>.
0882 */
0883 @Deprecated
0884 public void setSeconds(int seconds) {
0885 getCalendarDate().setSeconds(seconds);
0886 }
0887
0888 /**
0889 * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
0890 * represented by this <tt>Date</tt> object.
0891 *
0892 * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
0893 * represented by this date.
0894 */
0895 public long getTime() {
0896 return getTimeImpl();
0897 }
0898
0899 private final long getTimeImpl() {
0900 if (cdate != null && !cdate.isNormalized()) {
0901 normalize();
0902 }
0903 return fastTime;
0904 }
0905
0906 /**
0907 * Sets this <code>Date</code> object to represent a point in time that is
0908 * <code>time</code> milliseconds after January 1, 1970 00:00:00 GMT.
0909 *
0910 * @param time the number of milliseconds.
0911 */
0912 public void setTime(long time) {
0913 fastTime = time;
0914 cdate = null;
0915 }
0916
0917 /**
0918 * Tests if this date is before the specified date.
0919 *
0920 * @param when a date.
0921 * @return <code>true</code> if and only if the instant of time
0922 * represented by this <tt>Date</tt> object is strictly
0923 * earlier than the instant represented by <tt>when</tt>;
0924 * <code>false</code> otherwise.
0925 * @exception NullPointerException if <code>when</code> is null.
0926 */
0927 public boolean before(Date when) {
0928 return getMillisOf(this ) < getMillisOf(when);
0929 }
0930
0931 /**
0932 * Tests if this date is after the specified date.
0933 *
0934 * @param when a date.
0935 * @return <code>true</code> if and only if the instant represented
0936 * by this <tt>Date</tt> object is strictly later than the
0937 * instant represented by <tt>when</tt>;
0938 * <code>false</code> otherwise.
0939 * @exception NullPointerException if <code>when</code> is null.
0940 */
0941 public boolean after(Date when) {
0942 return getMillisOf(this ) > getMillisOf(when);
0943 }
0944
0945 /**
0946 * Compares two dates for equality.
0947 * The result is <code>true</code> if and only if the argument is
0948 * not <code>null</code> and is a <code>Date</code> object that
0949 * represents the same point in time, to the millisecond, as this object.
0950 * <p>
0951 * Thus, two <code>Date</code> objects are equal if and only if the
0952 * <code>getTime</code> method returns the same <code>long</code>
0953 * value for both.
0954 *
0955 * @param obj the object to compare with.
0956 * @return <code>true</code> if the objects are the same;
0957 * <code>false</code> otherwise.
0958 * @see java.util.Date#getTime()
0959 */
0960 public boolean equals(Object obj) {
0961 return obj instanceof Date
0962 && getTime() == ((Date) obj).getTime();
0963 }
0964
0965 /**
0966 * Returns the millisecond value of this <code>Date</code> object
0967 * without affecting its internal state.
0968 */
0969 static final long getMillisOf(Date date) {
0970 if (date.cdate == null) {
0971 return date.fastTime;
0972 }
0973 BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone();
0974 return gcal.getTime(d);
0975 }
0976
0977 /**
0978 * Compares two Dates for ordering.
0979 *
0980 * @param anotherDate the <code>Date</code> to be compared.
0981 * @return the value <code>0</code> if the argument Date is equal to
0982 * this Date; a value less than <code>0</code> if this Date
0983 * is before the Date argument; and a value greater than
0984 * <code>0</code> if this Date is after the Date argument.
0985 * @since 1.2
0986 * @exception NullPointerException if <code>anotherDate</code> is null.
0987 */
0988 public int compareTo(Date anotherDate) {
0989 long this Time = getMillisOf(this );
0990 long anotherTime = getMillisOf(anotherDate);
0991 return (this Time < anotherTime ? -1
0992 : (this Time == anotherTime ? 0 : 1));
0993 }
0994
0995 /**
0996 * Returns a hash code value for this object. The result is the
0997 * exclusive OR of the two halves of the primitive <tt>long</tt>
0998 * value returned by the {@link Date#getTime}
0999 * method. That is, the hash code is the value of the expression:
1000 * <blockquote><pre>
1001 * (int)(this.getTime()^(this.getTime() >>> 32))</pre></blockquote>
1002 *
1003 * @return a hash code value for this object.
1004 */
1005 public int hashCode() {
1006 long ht = this .getTime();
1007 return (int) ht ^ (int) (ht >> 32);
1008 }
1009
1010 /**
1011 * Converts this <code>Date</code> object to a <code>String</code>
1012 * of the form:
1013 * <blockquote><pre>
1014 * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
1015 * where:<ul>
1016 * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed,
1017 * Thu, Fri, Sat</tt>).
1018 * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun,
1019 * Jul, Aug, Sep, Oct, Nov, Dec</tt>).
1020 * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through
1021 * <tt>31</tt>), as two decimal digits.
1022 * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through
1023 * <tt>23</tt>), as two decimal digits.
1024 * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through
1025 * <tt>59</tt>), as two decimal digits.
1026 * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through
1027 * <tt>61</tt>, as two decimal digits.
1028 * <li><tt>zzz</tt> is the time zone (and may reflect daylight saving
1029 * time). Standard time zone abbreviations include those
1030 * recognized by the method <tt>parse</tt>. If time zone
1031 * information is not available, then <tt>zzz</tt> is empty -
1032 * that is, it consists of no characters at all.
1033 * <li><tt>yyyy</tt> is the year, as four decimal digits.
1034 * </ul>
1035 *
1036 * @return a string representation of this date.
1037 * @see java.util.Date#toLocaleString()
1038 * @see java.util.Date#toGMTString()
1039 */
1040 public String toString() {
1041 // "EEE MMM dd HH:mm:ss zzz yyyy";
1042 BaseCalendar.Date date = normalize();
1043 StringBuilder sb = new StringBuilder(28);
1044 int index = date.getDayOfWeek();
1045 if (index == gcal.SUNDAY) {
1046 index = 8;
1047 }
1048 convertToAbbr(sb, wtb[index]).append(' '); // EEE
1049 convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM
1050 CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2)
1051 .append(' '); // dd
1052
1053 CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH
1054 CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
1055 CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
1056 TimeZone zi = date.getZone();
1057 if (zi != null) {
1058 sb.append(zi.getDisplayName(date.isDaylightTime(),
1059 zi.SHORT, Locale.US)); // zzz
1060 } else {
1061 sb.append("GMT");
1062 }
1063 sb.append(' ').append(date.getYear()); // yyyy
1064 return sb.toString();
1065 }
1066
1067 /**
1068 * Converts the given name to its 3-letter abbreviation (e.g.,
1069 * "monday" -> "Mon") and stored the abbreviation in the given
1070 * <code>StringBuilder</code>.
1071 */
1072 private static final StringBuilder convertToAbbr(StringBuilder sb,
1073 String name) {
1074 sb.append(Character.toUpperCase(name.charAt(0)));
1075 sb.append(name.charAt(1)).append(name.charAt(2));
1076 return sb;
1077 }
1078
1079 /**
1080 * Creates a string representation of this <tt>Date</tt> object in an
1081 * implementation-dependent form. The intent is that the form should
1082 * be familiar to the user of the Java application, wherever it may
1083 * happen to be running. The intent is comparable to that of the
1084 * "<code>%c</code>" format supported by the <code>strftime()</code>
1085 * function of ISO C.
1086 *
1087 * @return a string representation of this date, using the locale
1088 * conventions.
1089 * @see java.text.DateFormat
1090 * @see java.util.Date#toString()
1091 * @see java.util.Date#toGMTString()
1092 * @deprecated As of JDK version 1.1,
1093 * replaced by <code>DateFormat.format(Date date)</code>.
1094 */
1095 @Deprecated
1096 public String toLocaleString() {
1097 DateFormat formatter = DateFormat.getDateTimeInstance();
1098 return formatter.format(this );
1099 }
1100
1101 /**
1102 * Creates a string representation of this <tt>Date</tt> object of
1103 * the form:
1104 * <blockquote<pre>
1105 * d mon yyyy hh:mm:ss GMT</pre></blockquote>
1106 * where:<ul>
1107 * <li><i>d</i> is the day of the month (<tt>1</tt> through <tt>31</tt>),
1108 * as one or two decimal digits.
1109 * <li><i>mon</i> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, Jul,
1110 * Aug, Sep, Oct, Nov, Dec</tt>).
1111 * <li><i>yyyy</i> is the year, as four decimal digits.
1112 * <li><i>hh</i> is the hour of the day (<tt>00</tt> through <tt>23</tt>),
1113 * as two decimal digits.
1114 * <li><i>mm</i> is the minute within the hour (<tt>00</tt> through
1115 * <tt>59</tt>), as two decimal digits.
1116 * <li><i>ss</i> is the second within the minute (<tt>00</tt> through
1117 * <tt>61</tt>), as two decimal digits.
1118 * <li><i>GMT</i> is exactly the ASCII letters "<tt>GMT</tt>" to indicate
1119 * Greenwich Mean Time.
1120 * </ul><p>
1121 * The result does not depend on the local time zone.
1122 *
1123 * @return a string representation of this date, using the Internet GMT
1124 * conventions.
1125 * @see java.text.DateFormat
1126 * @see java.util.Date#toString()
1127 * @see java.util.Date#toLocaleString()
1128 * @deprecated As of JDK version 1.1,
1129 * replaced by <code>DateFormat.format(Date date)</code>, using a
1130 * GMT <code>TimeZone</code>.
1131 */
1132 @Deprecated
1133 public String toGMTString() {
1134 // d MMM yyyy HH:mm:ss 'GMT'
1135 long t = getTime();
1136 BaseCalendar cal = getCalendarSystem(t);
1137 BaseCalendar.Date date = (BaseCalendar.Date) cal
1138 .getCalendarDate(getTime(), (TimeZone) null);
1139 StringBuilder sb = new StringBuilder(32);
1140 CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 1)
1141 .append(' '); // d
1142 convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM
1143 sb.append(date.getYear()).append(' '); // yyyy
1144 CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH
1145 CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
1146 CalendarUtils.sprintf0d(sb, date.getSeconds(), 2); // ss
1147 sb.append(" GMT"); // ' GMT'
1148 return sb.toString();
1149 }
1150
1151 /**
1152 * Returns the offset, measured in minutes, for the local time zone
1153 * relative to UTC that is appropriate for the time represented by
1154 * this <code>Date</code> object.
1155 * <p>
1156 * For example, in Massachusetts, five time zones west of Greenwich:
1157 * <blockquote><pre>
1158 * new Date(96, 1, 14).getTimezoneOffset() returns 300</pre></blockquote>
1159 * because on February 14, 1996, standard time (Eastern Standard Time)
1160 * is in use, which is offset five hours from UTC; but:
1161 * <blockquote><pre>
1162 * new Date(96, 5, 1).getTimezoneOffset() returns 240</pre></blockquote>
1163 * because on June 1, 1996, daylight saving time (Eastern Daylight Time)
1164 * is in use, which is offset only four hours from UTC.<p>
1165 * This method produces the same result as if it computed:
1166 * <blockquote><pre>
1167 * (this.getTime() - UTC(this.getYear(),
1168 * this.getMonth(),
1169 * this.getDate(),
1170 * this.getHours(),
1171 * this.getMinutes(),
1172 * this.getSeconds())) / (60 * 1000)
1173 * </pre></blockquote>
1174 *
1175 * @return the time-zone offset, in minutes, for the current time zone.
1176 * @see java.util.Calendar#ZONE_OFFSET
1177 * @see java.util.Calendar#DST_OFFSET
1178 * @see java.util.TimeZone#getDefault
1179 * @deprecated As of JDK version 1.1,
1180 * replaced by <code>-(Calendar.get(Calendar.ZONE_OFFSET) +
1181 * Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)</code>.
1182 */
1183 @Deprecated
1184 public int getTimezoneOffset() {
1185 int zoneOffset;
1186 if (cdate == null) {
1187 TimeZone tz = TimeZone.getDefaultRef();
1188 if (tz instanceof ZoneInfo) {
1189 zoneOffset = ((ZoneInfo) tz).getOffsets(fastTime, null);
1190 } else {
1191 zoneOffset = tz.getOffset(fastTime);
1192 }
1193 } else {
1194 normalize();
1195 zoneOffset = cdate.getZoneOffset();
1196 }
1197 return -zoneOffset / 60000; // convert to minutes
1198 }
1199
1200 private final BaseCalendar.Date getCalendarDate() {
1201 if (cdate == null) {
1202 BaseCalendar cal = getCalendarSystem(fastTime);
1203 cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime,
1204 TimeZone.getDefaultRef());
1205 }
1206 return cdate;
1207 }
1208
1209 private final BaseCalendar.Date normalize() {
1210 if (cdate == null) {
1211 BaseCalendar cal = getCalendarSystem(fastTime);
1212 cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime,
1213 TimeZone.getDefaultRef());
1214 return cdate;
1215 }
1216
1217 // Normalize cdate with the TimeZone in cdate first. This is
1218 // required for the compatible behavior.
1219 if (!cdate.isNormalized()) {
1220 cdate = normalize(cdate);
1221 }
1222
1223 // If the default TimeZone has changed, then recalculate the
1224 // fields with the new TimeZone.
1225 TimeZone tz = TimeZone.getDefaultRef();
1226 if (tz != cdate.getZone()) {
1227 cdate.setZone(tz);
1228 CalendarSystem cal = getCalendarSystem(cdate);
1229 cal.getCalendarDate(fastTime, cdate);
1230 }
1231 return cdate;
1232 }
1233
1234 // fastTime and the returned data are in sync upon return.
1235 private final BaseCalendar.Date normalize(BaseCalendar.Date date) {
1236 int y = date.getNormalizedYear();
1237 int m = date.getMonth();
1238 int d = date.getDayOfMonth();
1239 int hh = date.getHours();
1240 int mm = date.getMinutes();
1241 int ss = date.getSeconds();
1242 int ms = date.getMillis();
1243 TimeZone tz = date.getZone();
1244
1245 // If the specified year can't be handled using a long value
1246 // in milliseconds, GregorianCalendar is used for full
1247 // compatibility with underflow and overflow. This is required
1248 // by some JCK tests. The limits are based max year values -
1249 // years that can be represented by max values of d, hh, mm,
1250 // ss and ms. Also, let GregorianCalendar handle the default
1251 // cutover year so that we don't need to worry about the
1252 // transition here.
1253 if (y == 1582 || y > 280000000 || y < -280000000) {
1254 if (tz == null) {
1255 tz = TimeZone.getTimeZone("GMT");
1256 }
1257 GregorianCalendar gc = new GregorianCalendar(tz);
1258 gc.clear();
1259 gc.set(gc.MILLISECOND, ms);
1260 gc.set(y, m - 1, d, hh, mm, ss);
1261 fastTime = gc.getTimeInMillis();
1262 BaseCalendar cal = getCalendarSystem(fastTime);
1263 date = (BaseCalendar.Date) cal
1264 .getCalendarDate(fastTime, tz);
1265 return date;
1266 }
1267
1268 BaseCalendar cal = getCalendarSystem(y);
1269 if (cal != getCalendarSystem(date)) {
1270 date = (BaseCalendar.Date) cal.newCalendarDate(tz);
1271 date.setNormalizedDate(y, m, d)
1272 .setTimeOfDay(hh, mm, ss, ms);
1273 }
1274 // Perform the GregorianCalendar-style normalization.
1275 fastTime = cal.getTime(date);
1276
1277 // In case the normalized date requires the other calendar
1278 // system, we need to recalculate it using the other one.
1279 BaseCalendar ncal = getCalendarSystem(fastTime);
1280 if (ncal != cal) {
1281 date = (BaseCalendar.Date) ncal.newCalendarDate(tz);
1282 date.setNormalizedDate(y, m, d)
1283 .setTimeOfDay(hh, mm, ss, ms);
1284 fastTime = ncal.getTime(date);
1285 }
1286 return date;
1287 }
1288
1289 /**
1290 * Returns the Gregorian or Julian calendar system to use with the
1291 * given date. Use Gregorian from October 15, 1582.
1292 *
1293 * @param year normalized calendar year (not -1900)
1294 * @return the CalendarSystem to use for the specified date
1295 */
1296 private static final BaseCalendar getCalendarSystem(int year) {
1297 if (year >= 1582) {
1298 return gcal;
1299 }
1300 return getJulianCalendar();
1301 }
1302
1303 private static final BaseCalendar getCalendarSystem(long utc) {
1304 // Quickly check if the time stamp given by `utc' is the Epoch
1305 // or later. If it's before 1970, we convert the cutover to
1306 // local time to compare.
1307 if (utc >= 0
1308 || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER
1309 - TimeZone.getDefaultRef().getOffset(utc)) {
1310 return gcal;
1311 }
1312 return getJulianCalendar();
1313 }
1314
1315 private static final BaseCalendar getCalendarSystem(
1316 BaseCalendar.Date cdate) {
1317 if (jcal == null) {
1318 return gcal;
1319 }
1320 if (cdate.getEra() != null) {
1321 return jcal;
1322 }
1323 return gcal;
1324 }
1325
1326 synchronized private static final BaseCalendar getJulianCalendar() {
1327 if (jcal == null) {
1328 jcal = (BaseCalendar) CalendarSystem.forName("julian");
1329 }
1330 return jcal;
1331 }
1332
1333 /**
1334 * Save the state of this object to a stream (i.e., serialize it).
1335 *
1336 * @serialData The value returned by <code>getTime()</code>
1337 * is emitted (long). This represents the offset from
1338 * January 1, 1970, 00:00:00 GMT in milliseconds.
1339 */
1340 private void writeObject(ObjectOutputStream s) throws IOException {
1341 s.writeLong(getTimeImpl());
1342 }
1343
1344 /**
1345 * Reconstitute this object from a stream (i.e., deserialize it).
1346 */
1347 private void readObject(ObjectInputStream s) throws IOException,
1348 ClassNotFoundException {
1349 fastTime = s.readLong();
1350 }
1351 }
|