home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 October
/
Chip_1997-10_cd.bin
/
tema
/
sybase
/
powerj
/
java.z
/
Date.java
< prev
next >
Wrap
Text File
|
1996-05-03
|
17KB
|
612 lines
/*
* @(#)Date.java 1.21 95/11/21 James Gosling, Arthur van Hoff
*
* Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for NON-COMMERCIAL purposes and without fee is hereby
* granted provided that this copyright notice appears in all copies. Please
* refer to the file "copyright.html" for further important copyright and
* licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
* OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
* ITS DERIVATIVES.
*/
package java.util;
/**
* A wrapper for a date. This class lets you manipulate
* dates in a system independent way. To print today's
* date use:
* <pre>
* Date d = new Date();
* System.out.println("today = " + d);
* </pre>
* To find out what day corresponds to a particular date:
* <pre>
* Date d = new Date(63, 0, 16); // January 16, 1963
* System.out.println("Day of the week: " + d.getDay());
* </pre>
* The date can be set and examined
* according to the local time zone into the
* year, month, day, hour, minute and second.
* <p>
* While the API is intended to reflect UTC, Coordinated Universal Time,
* it doesn't do so exactly. This inexact behavior is inherited from
* the time system of the underlying OS. All modern OS's that I (jag)
* am aware of assume that 1 day = 24*60*60 seconds. In UTC, about once
* a year there is an extra second, called a "leap second" added to
* a day to account for the wobble of the earth. Most computer clocks
* are not accurate enough to be able to reflect this distinction.
* Some computer standards are defined in GMT, which is equivalent
* to UT, Universal Time. GMT is the "civil" name for the standard,
* UT is the "scientific" name for the same standard. The distinction
* between UTC and UT is that the first is based on an atomic clock and
* the second is based on astronomical observations, which for all
* practical purposes is an invisibly fine hair to split.
* An interesting source of further information is the
* US Naval Observatory, particularly the
* <a href=http://tycho.usno.navy.mil>Directorate of Time</a>
* and their definitions of
* <a href=http://tycho.usno.navy.mil/systime.html>Systems of Time</a>.
*
* @version 1.14, 28 Jul 1995
* @author James Gosling
* @author Arthur van Hoff
*/
public
class Date {
private long value;
private boolean valueValid;
private boolean expanded;
private short tm_millis; /* miliseconds within the second - [0,999] */
private byte tm_sec; /* seconds after the minute - [0, 61] for
* leap seconds */
private byte tm_min; /* minutes after the hour - [0, 59] */
private byte tm_hour; /* hour since midnight - [0, 23] */
private byte tm_mday; /* day of the month - [1, 31] */
private byte tm_mon; /* months since January - [0, 11] */
private byte tm_wday; /* days since Sunday - [0, 6] */
private short tm_yday; /* days since January 1 - [0, 365] */
private int tm_year; /* years since 1900 */
private int tm_isdst; /* flag for alternate daylight savings time */
/**
* Creates today's date/time.
*/
public Date () {
this(System.currentTimeMillis());
}
/**
* Creates a date.
* The fields are normalized before the Date object is created.
* The argument does not have to be in the correct range. For
* example, the 32nd of January is correctly interpreted as the
* 1st of February. You can use this to figure out what day a
* particular date falls on.
* @param date the value of the argument to be created
*/
public Date (long date) {
value = date;
valueValid = true;
expanded = false;
}
/**
* Creates a date.
* The fields are normalized before the Date object is created.
* The arguments do not have to be in the correct range. For example,
* the 32nd of January is correctly interpreted as the 1st of February.
* You can use this to figure out what day a particular date falls on.
* @param year a year after 1900
* @param month a month between 0-11
* @param date day of the month between 1-31
*/
public Date (int year, int month, int date) {
this(year, month, date, 0, 0, 0);
}
/**
* Creates a date.
* The fields are normalized before the Date object is created.
* The arguments do not have to be in the correct range. For example,
* the 32nd of January is correctly interpreted as the 1st of February.
* You can use this to figure out what day a particular date falls on.
* @param year a year after 1900
* @param month a month between 0-11
* @param date day of the month between 1-31
* @param hrs hours between 0-23
* @param min minutes between 0-59
*/
public Date (int year, int month, int date, int hrs, int min) {
this(year, month, date, hrs, min, 0);
}
/**
* Creates a date. The fields are normalized before the Date object is
* created. The arguments do not have to be in the correct range. For
* example, the 32nd of January is correctly interpreted as the 1st of
* February. You can use this to figure out what day a particular date
* falls on.
* @param year a year after 1900
* @param month a month between 0-11
* @param date day of the month between 1-31
* @param hrs hours between 0-23
* @param min minutes between 0-59
* @param sec seconds between 0-59
*/
public Date (int year, int month, int date, int hrs, int min, int sec) {
expanded = true;
valueValid = false;
tm_millis = 0;
tm_sec = (byte) sec;
tm_min = (byte) min;
tm_hour = (byte) hrs;
tm_mday = (byte) date;
tm_mon = (byte) month;
tm_wday = 0;
tm_yday = 0;
tm_year = year;
computeValue();
expand();
}
/**
* Creates a date from a string according to the syntax
* accepted by parse().
*/
public Date (String s) {
this(parse(s));
}
/**
* Calculates a UTC value from YMDHMS. Interpretes
* the parameters in UTC, <i>not<i> in the local time zone.
* @param year a year after 1900
* @param month a month between 0-11
* @param date day of the month between 1-31
* @param hrs hours between 0-23
* @param min minutes between 0-59
* @param sec seconds between 0-59
*/
public static long UTC(int year, int month, int date,
int hrs, int min, int sec) {
long day = (date
+ monthOffset[month]
+ ((year & 3) != 0
|| year % 100 == 0 && (year + 300) % 400 != 0
|| month < 2
? -1 : 0)/* convert day-of-month to 0 based range,
* except following February in a leap year,
* in which case we skip the conversion to
* account for the extra day in February */
+ (year - 70) * 365L // days per year
+ (year - 69) / 4 // plus leap days
- (year - 1) / 100 // no leap on century years
+ (year + 299) / 400); // except %400 years
return (sec + 60 * (min + 60 * hrs)) * 1000 + (60 * 60 * 24 * 1000) * day;
}
private static short monthOffset[] = {
0, // 31 January
31, // 28 February
59, // 31 March
90, // 30 April
120, // 31 May
151, // 30 June
181, // 31 July
212, // 31 August
243, // 30 September
273, // 31 October
304, // 30 November
334 // 31 December
// 365
};
/**
* Given a string representing a time, parse it and return the time value.
* It accepts many syntaxes, but most importantly, in accepts the IETF
* standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It understands
* the continental US time zone abbreviations, but for general use, a
* timezone offset should be used: "Sat, 12 Aug 1995 13:30:00 GMT+0430"
* (4 hours, 30 minutes west of the Greenwich meridian).
* If no time zone is specified, the local time zone is assumed.
* GMT and UTC are considered equivalent.
*/
public static long parse(String s) {
int year = -1;
int mon = -1;
int mday = -1;
int hour = -1;
int min = -1;
int sec = -1;
int millis = -1;
int c = -1;
int i = 0;
int n = -1;
int wst = -1;
int tzoffset = -1;
int prevc = 0;
syntax:
{
if (s == null)
break syntax;
int limit = s.length();
while (i < limit) {
c = s.charAt(i);
i++;
if (c <= ' ' || c == ',' || c == '-')
continue;
if (c == '(') { // skip comments
int depth = 1;
while (i < limit) {
c = s.charAt(i);
i++;
if (c == '(') depth++;
else if (c == ')')
if (--depth <= 0)
break;
}
continue;
}
if ('0' <= c && c <= '9') {
n = c - '0';
while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
n = n * 10 + c - '0';
i++;
}
if (prevc == '+' || prevc == '-' && year>=0) {
// timezone offset
if (n < 24)
n = n * 60; // EG. "GMT-3"
else
n = n % 100 + n / 100 * 60; // eg "GMT-0430"
if (prevc == '+') // plus means east of GMT
n = -n;
if (tzoffset != 0 && tzoffset != -1)
break syntax;
tzoffset = n;
} else if (n >= 70)
if (year >= 0)
break syntax;
else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
year = n < 1900 ? n : n - 1900;
else
break syntax;
else if (c == ':')
if (hour < 0)
hour = (byte) n;
else if (min < 0)
min = (byte) n;
else
break syntax;
else if (c == '/')
if (mon < 0)
mon = (byte) n;
else if (mday < 0)
mday = (byte) n;
else
break syntax;
else if (i < limit && c != ',' && c > ' ' && c != '-')
break syntax;
else if (hour >= 0 && min < 0)
min = (byte) n;
else if (min >= 0 && sec < 0)
sec = (byte) n;
else if (mday < 0)
mday = (byte) n;
else
break syntax;
prevc = 0;
} else if (c == '/' || c == ':' || c == '+' || c == '-')
prevc = c;
else {
int st = i - 1;
while (i < limit) {
c = s.charAt(i);
if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'))
break;
i++;
}
if (i <= st + 1)
break syntax;
int k;
for (k = wtb.length; --k >= 0;)
if (wtb[k].regionMatches(true, 0, s, st, i - st)) {
int action = ttb[k];
if (action != 0)
if (action == 1) // pm
if (hour > 12 || hour < 0)
break syntax;
else
hour += 12;
else if (action <= 13) // month!
if (mon < 0)
mon = (byte) (action - 2);
else
break syntax;
else
tzoffset = action - 10000;
break;
}
if (k < 0)
break syntax;
prevc = 0;
}
}
if (year < 0 || mon < 0 || mday < 0)
break syntax;
if (sec < 0)
sec = 0;
if (min < 0)
min = 0;
if (hour < 0)
hour = 0;
if (tzoffset == -1) // no time zone specified, have to use local
return new Date (year, mon, mday, hour, min, sec).getTime();
return UTC(year, mon, mday, hour, min, sec) + tzoffset * (60 * 1000);
}
// syntax error
throw new IllegalArgumentException();
}
private final static String wtb[] = {
"am", "pm",
"monday", "tuesday", "wednesday", "thursday", "friday",
"saturday", "sunday",
"january", "february", "march", "april", "may", "june",
"july", "august", "september", "october", "november", "december",
"gmt", "ut", "utc", "est", "edt", "cst", "cdt",
"mst", "mdt", "pst", "pdt"
// this time zone table needs to be expanded
};
private final static int ttb[] = {
0, 1, 0, 0, 0, 0, 0, 0, 0,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
10000 + 0, 10000 + 0, 10000 + 0, // GMT/UT/UTC
10000 + 5 * 60, 10000 + 4 * 60, // EST/EDT
10000 + 6 * 60, 10000 + 5 * 60,
10000 + 7 * 60, 10000 + 6 * 60,
10000 + 8 * 60, 10000 + 7 * 60
};
/**
* Returns the year after 1900.
*/
public int getYear() {
if (!expanded)
expand();
return tm_year;
}
/**
* Sets the year.
* @param year the year value
*/
public void setYear(int year) {
if (!expanded)
expand();
tm_year = year;
valueValid = false;
}
/**
* Returns the month. This method assigns months with the
* values 0-11, with January beginning at value 0.
*/
public int getMonth() {
if (!expanded)
expand();
return tm_mon;
}
/**
* Sets the month.
* @param month the month value (0-11)
*/
public void setMonth(int month) {
if (!expanded)
expand();
tm_mon = (byte) month;
valueValid = false;
}
/**
* Returns the day of the month. This method assigns days
* with the values of 1 to 31.
*/
public int getDate() {
if (!expanded)
expand();
return tm_mday;
}
/**
* Sets the date.
* @param date the day value
*/
public void setDate(int date) {
if (!expanded)
expand();
tm_mday = (byte) date;
valueValid = false;
}
/**
* Returns the day of the week. This method assigns days
* of the week with the values 0-6, with 0 being Sunday.
*/
public int getDay() {
if (!expanded) {
expand();
} else if ((tm_wday < 0) || !valueValid) {
computeValue();
expand();
}
return tm_wday;
}
/**
* Returns the hour. This method assigns the value of the
* hours of the day to range from 0 to 23, with midnight equal
* to 0.
*/
public int getHours() {
if (!expanded)
expand();
return tm_hour;
}
/**
* Sets the hours.
* @param hours the hour value
*/
public void setHours(int hours) {
if (!expanded)
expand();
tm_hour = (byte) hours;
valueValid = false;
}
/**
* Returns the minute. This method assigns the minutes of an
* hour to be any value from 0 to 59.
*/
public int getMinutes() {
if (!expanded)
expand();
return tm_min;
}
/**
* Sets the minutes.
* @param minutes the value of the minutes
*/
public void setMinutes(int minutes) {
if (!expanded)
expand();
tm_min = (byte) minutes;
valueValid = false;
}
/**
* Returns the second. This method assigns the seconds of
* a minute to values of 0-59.
*/
public int getSeconds() {
if (!expanded)
expand();
return tm_sec;
}
/**
* Sets the seconds.
* @param seconds the second value
*/
public void setSeconds(int seconds) {
if (!expanded)
expand();
tm_sec = (byte) seconds;
valueValid = false;
}
/**
* Returns the time in milliseconds since the epoch.
*/
public long getTime() {
if (!valueValid)
computeValue();
return value;
}
/**
* Sets the time.
* @param time The new time value in milliseconds since the epoch.
*/
public void setTime(long time) {
value = time;
valueValid = true;
expanded = false;
}
/**
* Checks whether this date comes before the specified date.
* @param when the date to compare
* @return true if the original date comes before the specified
* one; false otherwise.
*/
public boolean before(Date when) {
return getTime() < when.getTime();
}
/**
* Checks whether this date comes after the specified date.
* @param when the date to compare
* @return true if the original date comes after the specified
* one; false otherwise.
*/
public boolean after(Date when) {
return getTime() > when.getTime();
}
/**
* Compares this object against the specified object.
* @param obj the object to compare with
* @return true if the objects are the same; false otherwise.
*/
public boolean equals(Object obj) {
return obj != null && obj instanceof Date &&getTime() == ((Date) obj).getTime();
}
/**
* Computes a hashCode.
*/
public int hashCode() {
long ht = getTime();
return (int) ht ^ (int) (ht >> 32);
}
/**
* Converts a date to a String, using the UNIX ctime conventions.
*/
public native String toString();
/**
* Converts a date to a String, using the locale conventions.
*/
public native String toLocaleString();
/**
* Converts a date to a String, using the Internet GMT conventions.
*/
public native String toGMTString();
/**
* Return the time zone offset in minutes for the current locale that is appropriate
* for this time. This value would be a constant except for
* daylight savings time.
*/
public int getTimezoneOffset() {
if (!expanded)
expand();
return (int) ((getTime() - UTC(tm_year, tm_mon, tm_mday,
tm_hour, tm_min, tm_sec)) / (60 * 1000));
}
/*
* Gets date values.
*/
private native void expand();
private native void computeValue();
}