package java.util;
import java.text.DateFormat;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.lang.ref.SoftReference;
import sun.util.calendar.BaseCalendar;
import sun.util.calendar.CalendarDate;
import sun.util.calendar.CalendarSystem;
import sun.util.calendar.CalendarUtils;
import sun.util.calendar.Era;
import sun.util.calendar.Gregorian;
import sun.util.calendar.ZoneInfo;
类 Date 表示特定的瞬间,精确到毫秒。
在 JDK 1.1 之前,类 Date
有两个其他的函数。它允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和解析日期字符串。不过,这些函数的 API
不易于实现国际化。从 JDK 1.1 开始,应该使用 Calendar
类实现日期和时间字段之间转换,使用 DateFormat
类来格式化和解析日期字符串。Date 中的相应方法已废弃。
尽管 Date 类打算反映协调世界时 (UTC),但无法做到如此准确,这取决于 Java
虚拟机的主机环境。当前几乎所有操作系统都假定 1 天 =
24 × 60 × 60 =
86400 秒。但对于 UTC,大约每一两年出现一次额外的一秒,称为“闰秒”。闰秒始终作为当天的最后一秒增加,并且始终在 12 月
31 日或 6 月 30 日增加。例如,1995 年的最后一分钟是 61
秒,因为增加了闰秒。大多数计算机时钟不是特别的准确,因此不能反映闰秒的差别。
一些计算机标准是按照格林威治标准时 (GMT) 定义的,格林威治标准时和世界时 (UT) 是相等的。GMT
是标准的“民间”名称;UT 是相同标准的“科学”名称。UTC 和 UT 的区别是:UTC 是基于原子时钟的,UT
是基于天体观察的,两者在实际应用中难分轩轾。因为地球的旋转不是均匀的(它以复杂的方式减速和加速),所以 UT
始终不是均匀地流过。闰秒是根据需要引入 UTC 的,以便把 UTC 保持在 UT1 的 0.9 秒之内,UT1 是应用了某些更正的
UT 版本。还有其他的时间和日期系统;例如,基于卫星的全球定位系统 (GPS) 使用的时间刻度与 UTC 同步,但没有
针对闰秒进行调整。有关更多信息的一个有趣来源是美国海军天文台,特别是 Directorate of Time 的网址:
还有它们对 "Systems of Time" 的定义,网址为:
在类 Date
所有可以接受或返回年、月、日期、小时、分钟和秒值的方法中,将使用下面的表示形式:
年份 y 由整数
y - 1900
表示。
月份由从 0 至 11 的整数表示;0 是一月、1 是二月等等;因此 11 是十二月。
日期(一月中的某天)按通常方式由整数 1 至 31 表示。
小时由从 0 至 23 的整数表示。因此,从午夜到 1 a.m. 的时间是 0 点,从中午到 1 p.m. 的时间是 12
点。
分钟按通常方式由 0 至 59 的整数表示。
秒由 0 至 61 的整数表示;值 60 和 61 只对闰秒发生,尽管那样,也只用在实际正确跟踪闰秒的 Java
实现中。于按当前引入闰秒的方式,两个闰秒在同一分钟内发生是极不可能的,但此规范遵循 ISO C 的日期和时间约定。
在所有情形中,针对这些目的赋予方法的参数不需要在指定的范围内;例如,可以把日期指定为 1 月 32 日,并把它解释为 2 月 1
日的相同含义。
public class Date
implements
java.io.Serializable, Cloneable, Comparable
{
private static final
BaseCalendar gcal =
CalendarSystem.getGregorianCalendar();
private static
BaseCalendar jcal;
private transient long
fastTime;
private transient
BaseCalendar.Date cdate;
// Initialized just
before the value is used. See parse().
private static int
defaultCenturyStart;
private static final
long serialVersionUID = 7523967970034938905L;
分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。
public Date() {
this(System.currentTimeMillis());
}
分配Date对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即
1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。
public Date(long date)
{
fastTime = date;
}
返回此对象的副本。
public Object clone()
{
Date d = null;
try {
d =
(Date)super.clone();
if (cdate != null)
{
d.cdate = (BaseCalendar.Date) cdate.clone();
}
} catch (CloneNotSupportedException e) {} //
Won't happen
return d;
}
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"
};
private final static int
ttb[] = {
14, 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,
// CST/CDT
10000 + 7 * 60, 10000 + 6 * 60,
// MST/MDT
10000 + 8 * 60, 10000 + 7 * 60
//
PST/PDT
};
public long getTime()
{
return getTimeImpl();
}
private final long
getTimeImpl() {
if (cdate != null && !cdate.isNormalized()) {
normalize();
}
return fastTime;
}
public void setTime(long
time) {
fastTime = time;
cdate = null;
}
public boolean
before(Date when) {
return getMillisOf(this) <
getMillisOf(when);
}
public boolean
after(Date when) {
return getMillisOf(this) >
getMillisOf(when);
}
public boolean
equals(Object obj) {
return obj instanceof Date && getTime()
== ((Date) obj).getTime();
}
static final long
getMillisOf(Date date) {
if (date.cdate == null || date.cdate.isNormalized()) {
return
date.fastTime;
}
BaseCalendar.Date d = (BaseCalendar.Date)
date.cdate.clone();
return gcal.getTime(d);
}
public int
compareTo(Date anotherDate) {
long thisTime = getMillisOf(this);
long anotherTime = getMillisOf(anotherDate);
return (thisTime
}
public int hashCode()
{
long ht = this.getTime();
return (int) ht ^ (int) (ht >> 32);
}
public String toString()
{
// "EEE MMM dd HH:mm:ss zzz yyyy";
BaseCalendar.Date date = normalize();
StringBuilder sb = new StringBuilder(28);
int index = date.getDayOfWeek();
if (index == gcal.SUNDAY) {
index = 8;
}
convertToAbbr(sb, wtb[index]).append(' ');
// EEE
convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append('
'); // MMM
CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append('
'); // dd
CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');
// HH
CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':');
// mm
CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' ');
// ss
TimeZone zi = date.getZone();
if (zi != null) {
sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT,
Locale.US)); // zzz
} else {
sb.append("GMT");
}
sb.append(' ').append(date.getYear()); //
yyyy
return sb.toString();
}
private static final
StringBuilder convertToAbbr(StringBuilder sb, String name) {
sb.append(Character.toUpperCase(name.charAt(0)));
sb.append(name.charAt(1)).append(name.charAt(2));
return sb;
}
private final
BaseCalendar.Date getCalendarDate() {
if (cdate == null) {
BaseCalendar cal =
getCalendarSystem(fastTime);
cdate =
(BaseCalendar.Date) cal.getCalendarDate(fastTime,
TimeZone.getDefaultRef());
}
return cdate;
}
private final
BaseCalendar.Date normalize() {
if (cdate == null) {
BaseCalendar cal =
getCalendarSystem(fastTime);
cdate =
(BaseCalendar.Date) cal.getCalendarDate(fastTime,
TimeZone.getDefaultRef());
return cdate;
}
// Normalize cdate with the TimeZone in cdate first. This
is
// required for the compatible behavior.
if (!cdate.isNormalized()) {
cdate =
normalize(cdate);
}
// If the default TimeZone has changed, then recalculate
the
// fields with the new TimeZone.
TimeZone tz = TimeZone.getDefaultRef();
if (tz != cdate.getZone()) {
cdate.setZone(tz);
CalendarSystem cal =
getCalendarSystem(cdate);
cal.getCalendarDate(fastTime, cdate);
}
return cdate;
}
// fastTime and the
returned data are in sync upon return.
private final
BaseCalendar.Date normalize(BaseCalendar.Date date) {
int y = date.getNormalizedYear();
int m = date.getMonth();
int d = date.getDayOfMonth();
int hh = date.getHours();
int mm = date.getMinutes();
int ss = date.getSeconds();
int ms = date.getMillis();
TimeZone tz = date.getZone();
// If the specified year can't be handled using a long
value
// in milliseconds, GregorianCalendar is used for full
// compatibility with underflow and overflow. This is
required
// by some JCK tests. The limits are based max year values
-
// years that can be represented by max values of d, hh,
mm,
// ss and ms. Also, let GregorianCalendar handle the
default
// cutover year so that we don't need to worry about the
// transition here.
if (y == 1582 || y > 280000000 || y < -280000000)
{
if (tz == null) {
tz = TimeZone.getTimeZone("GMT");
}
GregorianCalendar gc =
new GregorianCalendar(tz);
gc.clear();
gc.set(gc.MILLISECOND,
ms);
gc.set(y, m-1, d, hh, mm,
ss);
fastTime =
gc.getTimeInMillis();
BaseCalendar cal =
getCalendarSystem(fastTime);
date =
(BaseCalendar.Date) cal.getCalendarDate(fastTime, tz);
return date;
}
BaseCalendar cal = getCalendarSystem(y);
if (cal != getCalendarSystem(date)) {
date =
(BaseCalendar.Date) cal.newCalendarDate(tz);
date.setNormalizedDate(y,
m, d).setTimeOfDay(hh, mm, ss, ms);
}
// Perform the GregorianCalendar-style normalization.
fastTime = cal.getTime(date);
// In case the normalized date requires the other
calendar
// system, we need to recalculate it using the other
one.
BaseCalendar ncal = getCalendarSystem(fastTime);
if (ncal != cal) {
date =
(BaseCalendar.Date) ncal.newCalendarDate(tz);
date.setNormalizedDate(y,
m, d).setTimeOfDay(hh, mm, ss, ms);
fastTime =
ncal.getTime(date);
}
return date;
}
private static final
BaseCalendar getCalendarSystem(int year) {
if (year >= 1582) {
return gcal;
}
return getJulianCalendar();
}
private static final
BaseCalendar getCalendarSystem(long utc) {
// Quickly check if the time stamp given by `utc' is the
Epoch
// or later. If it's before 1970, we convert the cutover
to
// local time to compare.
if (utc >= 0
|| utc >=
GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER
- TimeZone.getDefaultRef().getOffset(utc)) {
return gcal;
}
return getJulianCalendar();
}
private static final
BaseCalendar getCalendarSystem(BaseCalendar.Date cdate) {
if (jcal == null) {
return gcal;
}
if (cdate.getEra() != null) {
return jcal;
}
return gcal;
}
synchronized private
static final BaseCalendar getJulianCalendar() {
if (jcal == null) {
jcal = (BaseCalendar)
CalendarSystem.forName("julian");
}
return jcal;
}
private void
writeObject(ObjectOutputStream s)
throws IOException
{
s.writeLong(getTimeImpl());
}
private void
readObject(ObjectInputStream s)
throws IOException,
ClassNotFoundException
{
fastTime = s.readLong();
}
}
Java Date类详解
本文详细介绍了Java中的Date类,包括其构造方法、日期时间操作、序列化及克隆等功能。探讨了Date类如何表示特定瞬间,并说明了在JDK 1.1之后,推荐使用Calendar和DateFormat类进行日期和时间的操作。
1406

被折叠的 条评论
为什么被折叠?



