在JDK中,Calendar设置了正确的时区信息(包括夏令时信息)后,会自动根据夏令时规则进行日期和时间的设置。在Calendar中即存有原子时钟的值,也保存了在指定时区下的日期时间字符串值(年、月、日、时、分、秒......)。在设置原子时钟值或者修改日期时间时,Calendar会保证两种值的一致性。
Calendar是一个抽象类,JDK使用的默认子类是GregorianCalendar。GregorianCalendar是一种混合日历,在单一间断性的支持下同时支持儒略历和格里高利历系统。历史上,在那些首先采用格里高利历的国家/地区中,1582 年 10 月 4 日(儒略历)之后就是 1582 年 10 月 15 日(格里高利历)。此日历正确地模拟了这些变化。在开始格里高利历之前,GregorianCalendar 实现的是儒略历。
常见场景
在JAVA程序中,针对时区和夏令时,主要存在以下几个问题:
1.如何获得不同时区的时间
//获得同一个原子时钟在不同时区的时间,可以直接设置Calendar对象的时区。
calendar.setTimeZone(TimeZone.getTimeZone("America/Whitehorse"));
//如果只需要获得另一个时区的时间表达字符串,可以直接使用DateFormat。
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
DateFormat.FULL, Locale.US);
df.setTimeZone(TimeZone.getTimeZone("America/Whitehorse"));
df.format(calendar.getTime());
2.在存在夏令时的时区中,如何根据日期时间字段得到原子时钟
在存在夏令时跳变到标准时间时,会发生有一段区域存在两个相同的时间,比如一个是夏令时的1点半,一个是东令时的1点半。考虑这种情况,在给Calendar设置值的时候必须制定夏令时的偏移信息。
//设置美国时间2011-11-6 01:30:00(在重复时间范围内)
// 设置冬令时时间,无需设置夏令时偏移量
calendar.set(2011, Calendar.NOVEMBER, 6, 1, 30, 0);
// 设置夏令时时间,需要设置夏令时偏移量
calendar.set(2011, Calendar.NOVEMBER, 6, 1, 30, 0);
calendar.set(Calendar.DST_OFFSET, calendar.getTimeZone().getDSTSavings());