前面我们处理的时候都是基于本地,根本就没有考虑时区的问题,同时前面所提及的相关日期时间类也不包含时区信息。
时区是按照一定的规则将区域划分成的标准时间相同的区间。 java.time.ZoneId
表示的就是时区ID,每个特定
的 ZoneId
对象都有一个地区ID标识,一旦得到一个 ZoneId 对象,你就可以将它与 LocalDate
、LocalDateTime
或者是 Instant
对象整合起来,构造为一个 ZonedDateTime
实例,它代表了相对于指定时区的日期时间点。
地区ID都格式为“{区域}/{城市}”,这些地区集合的设定都由英特网编号分配机构(IANA)的时区数据库提供。
我们所使用的一般都是:Asia/Shanghai
Set<String> allId = ZoneId.getAvailableZoneIds(); // 获取所有可用的ZoneID
for (String string : allId) {
System.out.println(string);
}
通过上图我们对 ZonedDateTime
的组成部分有了清晰的了解,也可以明白 LocaleDate
、LocalTime
、 LocalDateTime
以及 ZoneId
之间的差异。
ZoneId romeZone = ZoneId.of("Europe/Rome");
LocalDate date = LocalDate.of(2014, Month.MARCH, 18); // 2014-03-18
ZonedDateTime zdt1 = date.atStartOfDay(romeZone); // 2014-03-18T00:00+01:00[Europe/Rome]
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); // 2014-03-18T13:45
ZonedDateTime zdt2 = dateTime.atZone(romeZone); // 2014-03-18T13:45+01:00[Europe/Rome]
LocalDateTime dateTimeLocal =LocalDateTime.now(); // 2019-08-10T11:26:21.161
Instant instant = Instant.now();
ZonedDateTime zdt3 = instant.atZone(romeZone); // 2019-08-10T05:26:21.162+02:00[Europe/Rome]
通过 ZoneId
,你还可以将 LocalDateTime
转换为 Instant
:
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
Instant instantFromDateTime = dateTime.toInstant(romeZone);
我们也可以通过反向的方式得到 LocalDateTime
对象:
Instant instant = Instant.now();
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);
注意事项:ZoneId
是一个抽象类,其自身提供了许多静态方法来构造 ZoneId
实例,其只有一个实现类 ZoneOffset
其对ZoneId
进行了相应的拓展。
拓展:
ISO-8601日历系统是世界文明日历系统的事实标准。但是,Java 8中另外还提供了4种其他的日历系统。这些日历系统中的每一个都有一个对应的日志类,分别是 ThaiBuddhistDate 、MinguoDate 、 JapaneseDate 以及 HijrahDate 。更多详细信息可参考《Java 8 实战》