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: }
|