标签:
Date
Date 表示特定的瞬间,精确到毫秒。在JDK1.1之前,Date有两个其他的函数。它允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和解析日期字符串。不过,这些函数的API不易于实现国际化。从JDK1.1开始,应该使用Calendar类实现日期和时间字段之间转换,使用DateFormat类来格式化和解析日期字符串。Date中的相应方法已废弃。
Date使用UTC时间,如Thu Jun 30 17:12:57 CST 2016,CST表示China Standard Time UT+8:00。尽管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同步,但没有针对闰秒进行调整。
大部分Date的方法都过时了,由Calendar类的方法替代,以下是几个重要的方法:
构造方法
public Date()
当前时间。
public Date(long date)
分配Date对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。
例子:
public static void main(String[] args) {
System.out.println(new Date());//Thu Jan 01 08:00:00 CST 1970 CST表示UTC+8,所以是8点
}
其他
public boolean after(Date when)
测试此日期是否在指定日期之后。
public boolean before(Date when)
测试此日期是否在指定日期之前。
public int compareTo(Date anotherDate)
比较两个日期的顺序。
如果参数Date等于此Date,则返回值0;如果此Date在Date参数之前,则返回小于0的值;如果此Date在Date参数之后,则返回大于0的值。
public boolean equals(Object obj)
比较两个日期的相等性。当且仅当参数不为null,并且是一个表示与此对象相同的时间点(到毫秒)的Date对象时,结果才为true。
因此,当且仅当getTime方法对于两个Date对象返回相同的long值时,这两个对象才是相等的。
public long getTime()
返回自1970 年 1 月 1 日 00:00:00 GMT以来此Date对象表示的毫秒数。
public void setTime(long time)
设置此Date对象,以表示1970 年 1 月 1 日 00:00:00 GMT以后time毫秒的时间点。
TimeZone
TimeZone表示时区偏移量,也可以计算夏令时。
通常,使用getDefault获取TimeZone,getDefault基于程序运行所在的时区创建TimeZone。例如,对于在日本运行的程序,getDefault基于日本标准时间创建TimeZone对象。
也可以用getTimeZone及时区ID获取TimeZone。例如美国太平洋时区的时区ID是"America/Los_Angeles"。因此,可以使用下面语句获得美国太平洋时间TimeZone对象:TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
可以使用getAvailableIDs方法来对所有受支持的时区ID进行迭代。可以选择受支持的ID来获得TimeZone。
如果想要的时区无法用受支持的ID之一表示,那么可以指定自定义时区ID来生成TimeZone。自定义时区ID的语法是:
NormalizedCustomID:
GMT Sign TwoDigitHours : Minutes
Sign:下面之一
+ -
TwoDigitHours:
Digit Digit
Minutes:
Digit Digit
Digit:下面之一
0 1 2 3 4 5 6 7 8 9
例如,TimeZone.getTimeZone("GMT-8").getID()返回"GMT-08:00"。
Hours必须在0至23之间,Minutes必须在00至59之间。例如,"GMT+10"和"GMT+0010"分别意味着比GMT提前10小时和10分钟。
为了与JDK1.1.x兼容,一些三字母时区ID(比如"PST"、"CTT"、"AST")也受支持。但是,它们的使用被废弃,这是因为相同的缩写经常用于多个时区(例如"CST"可以是美国的"Central Standard Time"和"China Standard Time"),但是 Java平台只可以识别其中一种。
例子:
public static void main(String[] args) {
TimeZone timeZone = TimeZone.getDefault();
System.out.println(timeZone.getDisplayName(true, TimeZone.LONG));//中国夏令时
System.out.println(timeZone.getDisplayName(false, TimeZone.LONG));//中国标准时间
System.out.println(timeZone.getDisplayName(true, TimeZone.SHORT));//CDT
System.out.println(timeZone.getDisplayName(false, TimeZone.SHORT));//CST
System.out.println(timeZone.getID());//Asia/Shanghai
TimeZone timeZone1 = TimeZone.getTimeZone("AST");
System.out.println(timeZone1.getDisplayName(true, TimeZone.LONG));//阿拉斯加夏令时
System.out.println(timeZone1.getDisplayName(false, TimeZone.LONG));//阿拉斯加标准时间
System.out.println(timeZone1.getDisplayName(true, TimeZone.SHORT));//AKDT
System.out.println(timeZone1.getDisplayName(false, TimeZone.SHORT));//AKST
System.out.println(timeZone1.getID());//AST
TimeZone timeZone2 = TimeZone.getTimeZone("America/Los_Angeles");
System.out.println(timeZone2.getDisplayName(true, TimeZone.LONG));//太平洋夏令时
System.out.println(timeZone2.getDisplayName(false, TimeZone.LONG));//太平洋标准时间
System.out.println(timeZone2.getDisplayName(true, TimeZone.SHORT));//PDT
System.out.println(timeZone2.getDisplayName(false, TimeZone.SHORT));//PST
System.out.println(timeZone2.getID());//America/Los_Angeles
TimeZone timeZone3 = TimeZone.getTimeZone("GMT+0010");
System.out.println(timeZone3.getDisplayName(true, TimeZone.LONG));//GMT+00:10
System.out.println(timeZone3.getDisplayName(false, TimeZone.LONG));//GMT+00:10
System.out.println(timeZone3.getDisplayName(true, TimeZone.SHORT));//GMT+00:10
System.out.println(timeZone3.getDisplayName(false, TimeZone.SHORT));//GMT+00:10
System.out.println(timeZone3.getID());//GMT+00:10
}
Calendar
Calendar类是一个抽象类,它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间1970 年 1 月 1 日的00:00:00.000,格里高利历)的偏移量。由于Calendar是抽象类,它有多个子类,例如GregorianCalendar(格里高利历或称公历)、JapaneseImperialCalendar(JDK7.0增加)。与其他语言环境敏感类一样,Calendar 提供了一个类方法getInstance,以获得此类型的一个通用的对象。Calendar的getInstance方法返回一个Calendar子类的对象,其日历字段已由当前日期和时间初始化:
public static Calendar getInstance()
返回的 Calendar 基于当前时间,使用了默认时区和默认语言环境。
public static Calendar getInstance(Locale aLocale)
返回的 Calendar 基于当前时间,使用了默认时区和给定的语言环境。
public static Calendar getInstance(TimeZone zone)
返回的 Calendar 基于当前时间,使用了给定时区和默认语言环境。
public static Calendar getInstance(TimeZone zone,Locale aLocale)
返回的 Calendar 基于当前时间,使用了给定的时区和给定的语言环境。
Calendar使用两个参数定义了特定于语言环境的7天制星期:
星期的第一天(firstDayOfWeek):例如,在美国,这一天是SUNDAY,而在法国,这一天是MONDAY,在Calendar类中,中国默认也是SUNDAY。
一年中第一个星期所需的最少天数(minimalDaysInFirstWeek):范围是1-7。
这些数字取自构造Calendar时的Locale。还可以通过为其设置值的方法来显式地指定它们。
获得并设置日历字段值
可以通过调用set方法来设置日历字段值。在需要计算时间值(距历元所经过的毫秒)或日历字段值之前,不会解释Calendar中的所有字段值设置。调用get、getTimeInMillis、getTime、add 和roll涉及此类计算。
宽松性
Calendar有两种解释日历字段的模式,即lenient和non-lenient。当Calendar处于 lenient 模式时,它可接受比它所生成的日历字段范围更大范围内的值。当Calendar重新计算日历字段值,以便由get()返回这些值时,所有日历字段都被标准化。例如,lenient模式下的GregorianCalendar将MONTH == JANUARY、DAY_OF_MONTH == 32解释为February 1。
当Calendar处于non-lenient模式时,如果其日历字段中存在任何不一致性,它都会抛出一个异常。例如,GregorianCalendar总是在1与月份的长度之间生成DAY_OF_MONTH值。如果已经设置了任何超出范围的字段值,那么在计算时间或日历字段值时,处于non-lenient模式下的GregorianCalendar会抛出一个异常。public void setLenient(boolean lenient)可以设置宽松性。
日历字段解析
在计算日历字段中的日期和时间时,可能没有足够的信息用于计算(例如只有年和月,但没有日),或者可能有不一致的信息( 例如 "Tuesday, July 15, 1996"(格林威治时间)——实际上,1996 年 7 月 15 日是星期一 )。Calendar将解析日历字段值,以便用以下方式确定日期和时间。
如果日历字段值中存在任何冲突,则Calendar将为最近设置的日历字段提供优先权。以下是日历字段的默认组合。将使用由最近设置的单个字段所确定的最近组合。
YEAR + MONTH + DAY_OF_MONTH
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
YEAR + DAY_OF_YEAR
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
HOUR_OF_DAY
AM_PM + HOUR
如果在选定的字段组合中,还有尚未设置值的任一日历字段,那么Calendar将使用其默认值。每个字段的默认值可能依据具体的日历系统而有所不同。例如,在GregorianCalendar中,字段的默认值与历元起始部分的字段值相同:即YEAR = 1970、MONTH = JANUARY、DAY_OF_MONTH = 1,等等。
GregorianCalendar
GregorianCalendar是Calendar最重要的一个子类,提供了世界上大多数国家/地区使用的标准日历系统。 GregorianCalendar是一种混合日历,在单一间断性的支持下同时支持儒略历和格里高利历系统。setGregorianChange(Date date)设置GregorianCalendar的更改日期。这是发生从儒略历日期切换到格里高利历日期的点。默认时间是1582 年 10 月 15 日(格里高利历)。在此之前,日期是按照儒略历计算的。 要得到纯粹的儒略历日历,可将更改日期设置为Date(Long.MAX_VALUE)。要得到一个纯粹的格里高利历日历,可将更改日期设置为Date(Long.MIN_VALUE)。 历史上,在那些首先采用格里高利历的国家/地区中,1582 年 10 月 4 日(儒略历)之后就是 1582 年 10 月 15 日(格里高利历)。此日历正确地模拟了这些变化。在开始格里高利历之前,GregorianCalendar实现的是儒略历。格里高利历和儒略历之间的唯一区别就是闰年规则。儒略历指定每 4 年就为闰年,而格里高利历则忽略不能被400整除的世纪年。在格里高利历创立以前,新年是3 月 25 日。为了避免混淆,此日历始终使用1 月 1 日为新年。如果想要格里高利历转换之前并且处于1 月 1 日和 3 月 24 日之间的日期,则可以进行手动调整。
WEEK_OF_YEAR 字段值的范围从1 到 53。一年的第一个星期始于getFirstDayOfWeek()的最早7天,至少包含该年的getMinimalDaysInFirstWeek()天。这取决于getMinimalDaysInFirstWeek()、getFirstDayOfWeek()的值以及1 月 1 日是星期几。一年的第一个星期和下一年的第一个星期之间的各个星期按顺序从2到52或53(根据需要)进行编号。
例如,1998 年 1 月 1 日是星期四。如果getFirstDayOfWeek()为MONDAY,并且getMinimalDaysInFirstWeek()为4(这些值反映了ISO 8601和很多国家/地区标准),则1998 年的第一个星期开始于1997 年 12 月 29 日,结束于1998 年 1 月 4 日。但是,如果getFirstDayOfWeek()为SUNDAY,那么1998年的第一个星期开始于1998 年 1 月 4 日,结束于1998 年 1 月 10 日;1998年头三天是1997 年第53个星期的一部分。
WEEK_OF_MONTH 字段值的范围从0到6。一个月的第一个星期(WEEK_OF_MONTH = 1 的日期)是该月至少连续 getMinimalDaysInFirstWeek() 天中的最早日期,结束于 getFirstDayOfWeek() 的前一天。与一年的第一个星期不同,一个月的第一个星期可能短于7天,也不必从getFirstDayOfWeek()这一天开始,并且不包括前一个月的日期。在第一个星期之前该月日期的WEEK_OF_MONTH为0。
例如,如果getFirstDayOfWeek() 为SUNDAY,getMinimalDaysInFirstWeek()为4,那么1998 年 1 月的第一个星期是从1 月 4 日星期日到1 月 10 日星期六。这些天的 WEEK_OF_MONTH 为1。1 月 1 日星期四到1 月 3 日星期六的WEEK_OF_MONTH为0。如果getMinimalDaysInFirstWeek() 变为3,则1 月 1 日到1 月 3 日的 WEEK_OF_MONTH 为 1。
clear方法将日历字段设置为未定义。GregorianCalendar为每个日历字段使用以下默认值(如果该值未定义)。
字段 |
默认值 |
ERA |
AD |
YEAR |
1970 |
MONTH |
JANUARY |
DAY_OF_MONTH |
1 |
DAY_OF_WEEK |
一个星期的第一天 |
WEEK_OF_MONTH |
0 |
DAY_OF_WEEK_IN_MONTH |
1 |
AM_PM |
AM |
HOUR, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND |
0 |
字段操作
set(f, value)
将日历字段f更改为value。此外,它设置了一个内部成员变量,以指示日历字段f已经被更改。尽管日历字段f是立即更改的,但是直到下次调用get()、getTime()、getTimeInMillis()、add() 或 roll()时才会重新计算日历的时间值(以毫秒为单位)。因此,多次调用set()不会触发多次不必要的计算。使用set()更改日历字段的结果是,其他日历字段也可能发生更改,这取决于日历字段、日历字段值和日历系统。
示例:假定GregorianCalendar最初被设置为1999 年 8 月 31 日。调用set(Calendar.MONTH, Calendar.SEPTEMBER)将该日期设置为 1999 年 9 月 31 日。这是1999 年 10 月 1 日的一个暂时内部表示。此时月份按道理应该是10月,但是,在调用getTime()之前调用set(Calendar.DAY_OF_MONTH, 30) 会将该日期设置为1999 年 9 月 30 日,因为在调用set()之后没有发生重新计算。
add(f, delta)
将delta添加到f字段中。这等同于调用set(f, get(f) + delta)。与set()不同,add()强迫日历系统立即重新计算日历的毫秒数和所有字段。add()有两个规则:
1、调用后f字段的值减去调用前f字段的值等于delta,字段f字段值超出其范围时,下一个更大的字段会递增或递减,并将字段值调整回其范围内。
2、如果期望某一个更小的字段是不变的,但让它等于以前的值是不可能的,因为在字段f发生更改之后,或者在出现其他约束之后,比如时区偏移量发生更改,它的最大值和最小值也在发生更改,然后它的值被调整为尽量接近于所期望的值。更小的字段表示一个更小的时间单元,例如HOUR是一个比DAY_OF_MONTH更小的字段。对于不期望是不变字段的更小字段,无需进行任何调整。日历系统例如格里高利历等会确定期望不变的那些字段。
示例:假定GregorianCalendar最初被设置为1999 年 8 月 31 日。调用add(Calendar.MONTH, 13) 将日历设置为2000 年 9 月 30 日。Add 规则1 MONTH字段设置为September,因为向August添加13个月得出的就是下一年的September。因为在GregorianCalendar 中,DAY_OF_MONTH不可能是9 月 31 日,所以add 规则2将DAY_OF_MONTH设置为30,即最可能的值。尽管DAY_OF_WEEK是一个更小的字段,但不能根据规则2调整DAY_OF_WEEK,因为在GregorianCalendar中的月份发生变化时,该值也需要发生变化。这个例子可以理解为,月份往后增加13个月后的月份最后一天。
roll(f, delta)
将delta添加到f字段中,这等同于调用add(f, delta),但不更改更大的字段。更大的字段表示一个更大的时间单元。DAY_OF_MONTH 是一个比HOUR大的字段。
add和roll的区别
原来设置为1999 年 8 月 31 日的GregorianCalendar 。现在调用roll(Calendar.MONTH, 8) 将该日历设置为1999 年 4 月 30 日。如果使用GregorianCalendar,则4月份的DAY_OF_MONTH字段不可能为 31。将DAY_OF_MONTH设置为最可能接近的值30。YEAR字段保持为值1999,因为它是一个比MONTH 更大的字段,所以不能改变。
原来设置为1999 年 6 月 6日星期日的GregorianCalendar 。现在调用roll(Calendar.WEEK_OF_MONTH, -1) 将该日历设置为1999 年 6 月 1 日星期二,而调用add(Calendar.WEEK_OF_MONTH, -1) 则将日历设置为1999 年 5 月 30 日星期日。这是因为上升和下降规则施加了其他的约束:WEEK_OF_MONTH改变时MONTH必须不变。所得日期必定在6 月 1日星期二和6 月 5 日星期六之间。DAY_OF_WEEK(在改变WEEK_OF_MONTH时它是一个不变量)被设置为Tuesday,是最接近Sunday的可能值(其中星期日是一个星期的第一天)。
构造方法
public GregorianCalendar()
在具有默认语言环境的默认时区内使用当前时间构造一个默认的GregorianCalendar。
public GregorianCalendar(TimeZone zone)
在具有默认语言环境的给定时区内构造一个基于当前时间的GregorianCalendar。
public GregorianCalendar(Locale aLocale)
在具有给定语言环境的默认时区内构造一个基于当前时间的GregorianCalendar。
public GregorianCalendar(TimeZone zone,Locale aLocale)
在具有给定语言环境的给定时区内构造一个基于当前时间的GregorianCalendar。
public GregorianCalendar(int year,int month, int dayOfMonth)
在具有默认语言环境的默认时区内构造一个带有给定日期设置的GregorianCalendar。
public GregorianCalendar(int year,int month,int dayOfMonth,int hourOfDay, int minute)
为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的GregorianCalendar。
public GregorianCalendar(int year, int month,int dayOfMonth,int hourOfDay,int minute,int second)
为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的GregorianCalendar。
例子:
private static String getDayOfWeek(int i) {
switch (i) {
case Calendar.SUNDAY:
return "星期日";
case Calendar.MONDAY:
return "星期一";
case Calendar.TUESDAY:
return "星期二";
case Calendar.WEDNESDAY:
return "星期三";
case Calendar.THURSDAY:
return "星期四";
case Calendar.FRIDAY:
return "星期五";
case Calendar.SATURDAY:
return "星期六";
default:
return "";
}
}
public static void main(String[] args) {
//当前时间,设置GregorianCalendar的环境为中国所在时区和中国的语言环境
GregorianCalendar gregorianCalendar = new GregorianCalendar(TimeZone.getTimeZone("GMT+8"), Locale.CHINA);
//获取每周第一天和每年第一周的最少天数
System.out.println("每年第一周的最少天数:" + gregorianCalendar.getMinimalDaysInFirstWeek());
System.out.println("每周第一天是:" + getDayOfWeek(gregorianCalendar.getFirstDayOfWeek()));
//即使设置了中国语言环境,这里获取到的每周第一天还是星期日,因此需要手动设置
gregorianCalendar.setFirstDayOfWeek(Calendar.MONDAY);
System.out.println("每周第一天是:" + getDayOfWeek(gregorianCalendar.getFirstDayOfWeek()));
//打印各个字段
System.out.println("公元前或者公元后:" + (gregorianCalendar.get(Calendar.ERA) == GregorianCalendar.BC ? "公元前" :
(gregorianCalendar.get(Calendar.ERA) == GregorianCalendar.AD ? "公元" : "")));
System.out.println("年:" + gregorianCalendar.get(Calendar.YEAR));
//月份从0-11
System.out.println("月:" + (gregorianCalendar.get(Calendar.MONTH) + 1));
System.out.println("当前年中第几周:" + gregorianCalendar.get(Calendar.WEEK_OF_YEAR));
System.out.println("当前年中第几天:" + gregorianCalendar.get(Calendar.DAY_OF_YEAR));
System.out.println("当前月中第几周:" + gregorianCalendar.get(Calendar.WEEK_OF_MONTH));
//1到7总是对应于DAY_OF_WEEK_IN_MONTH 1;8 到 14总是对应于DAY_OF_WEEK_IN_MONTH 2,依此类推
//负数是从末尾开始计算,固定一周为7天
System.out.println("当前月中第几周(固定):" + gregorianCalendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
System.out.println("当前月中第几天:" + gregorianCalendar.get(Calendar.DATE));
System.out.println("当前月中第几天:" + gregorianCalendar.get(Calendar.DAY_OF_MONTH));
System.out.println("星期:" + getDayOfWeek(gregorianCalendar.get(Calendar.DAY_OF_WEEK)));
System.out.println("上午或者下午:" + (gregorianCalendar.get(Calendar.AM_PM) == GregorianCalendar.AM ? "上午" :
(gregorianCalendar.get(Calendar.AM_PM) == GregorianCalendar.PM ? "下午" : "")));
//上午或下午的小时。HOUR用于12小时制时钟 (0 - 11)。中午和午夜用0表示,不用12表示。
System.out.println("小时:" + gregorianCalendar.get(Calendar.HOUR));
//一天中的小时。HOUR_OF_DAY用于24小时制时钟。
System.out.println("小时:" + gregorianCalendar.get(Calendar.HOUR_OF_DAY));
System.out.println("分钟:" + gregorianCalendar.get(Calendar.MINUTE));
System.out.println("秒钟:" + gregorianCalendar.get(Calendar.SECOND));
System.out.println("毫秒:" + gregorianCalendar.get(Calendar.MILLISECOND));
//以毫秒为单位指示距GMT的大致偏移量
System.out.println("时区偏移量:" + gregorianCalendar.get(Calendar.ZONE_OFFSET));
//以毫秒为单位指示夏令时的偏移量。
System.out.println("夏令时偏移量:" + gregorianCalendar.get(Calendar.DST_OFFSET));
}
输出:
每年第一周的最少天数:1
每周第一天是:星期日
每周第一天是:星期一
公元前或者公元后:公元
年:2016
月:7
当前年中第几周:28
当前年中第几天:186
当前月中第几周:2
当前月中第几周(固定):1
当前月中第几天:4
当前月中第几天:4
星期:星期一
上午或者下午:上午
小时:10
小时:10
分钟:50
秒钟:13
毫秒:461
时区偏移量:28800000
夏令时偏移量:0
其他用法请参考JDK API帮助文档。
java.util.Date和java.util.Calendar及相关类
标签:
原文地址:http://www.cnblogs.com/gjb724332682/p/5639799.html