时区和偏移类
原文: https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html
时区是使用相同标准时间的地球区域。每个时区由标识符描述,并且通常具有格式区域/城市(亚洲/东京)和格林威治/ UTC 时间的偏移。例如,东京的偏移是+09:00 。
ZoneId 和 ZoneOffset
Date-Time API 提供了两个用于指定时区或偏移的类:
ZoneId指定时区标识符,并提供在Instant和LocalDateTime之间进行转换的规则。ZoneOffset指定从格林威治/ UTC 时间偏移的时区。
格林威治/ UTC 时间的偏差通常以整个小时定义,但也有例外。以下代码来自 `TimeZoneId `示例,打印使用格林威治/ UTC 偏移的所有时区列表,这些时区未在整个小时内定义。
Set<String> allZones = ZoneId.getAvailableZoneIds();LocalDateTime dt = LocalDateTime.now();// Create a List using the set of zones and sort it.List<String> zoneList = new ArrayList<String>(allZones);Collections.sort(zoneList);...for (String s : zoneList) {ZoneId zone = ZoneId.of(s);ZonedDateTime zdt = dt.atZone(zone);ZoneOffset offset = zdt.getOffset();int secondsOfHour = offset.getTotalSeconds() % (60 * 60);String out = String.format("%35s %10s%n", zone, offset);// Write only time zones that do not have a whole hour offset// to standard out.if (secondsOfHour != 0) {System.out.printf(out);}...}
此示例将以下列表打印到标准输出:
America/Caracas -04:30America/St_Johns -02:30Asia/Calcutta +05:30Asia/Colombo +05:30Asia/Kabul +04:30Asia/Kathmandu +05:45Asia/Katmandu +05:45Asia/Kolkata +05:30Asia/Rangoon +06:30Asia/Tehran +04:30Australia/Adelaide +09:30Australia/Broken_Hill +09:30Australia/Darwin +09:30Australia/Eucla +08:45Australia/LHI +10:30Australia/Lord_Howe +10:30Australia/North +09:30Australia/South +09:30Australia/Yancowinna +09:30Canada/Newfoundland -02:30Indian/Cocos +06:30Iran +04:30NZ-CHAT +12:45Pacific/Chatham +12:45Pacific/Marquesas -09:30Pacific/Norfolk +11:30
TimeZoneId示例还会将所有时区 ID 的列表打印到名为 `timeZones `的文件中。
日期时间类
Date-Time API 提供了三个适用于时区的基于时间的类:
ZonedDateTime使用相应时区处理日期和时间,时区偏离格林威治/ UTC。OffsetDateTime使用与格林威治/ UTC 相对应的时区偏移处理日期和时间,没有时区 ID。OffsetTime处理与格林威治/ UTC 相对应的时区偏移的时间,没有时区 ID。
你何时会使用OffsetDateTime而不是ZonedDateTime ?如果您正在编写复杂的软件,根据地理位置为自己的日期和时间计算规则建模,或者如果您将时间戳存储在仅跟踪格林威治/ UTC 时间的绝对偏移的数据库中,那么您可能希望使用OffsetDateTime 。此外,XML 和其他网络格式将日期时间传输定义为OffsetDateTime或OffsetTime 。
虽然所有三个类都保持与格林威治/ UTC 时间的偏移,但只有ZonedDateTime使用 ZoneRules, java.time.zone的一部分包,用于确定特定时区的偏移量如何变化。例如,当将时钟向前移动到夏令时时,大多数时区经历间隙(通常为 1 小时),并且当将时钟移回标准时间和重复转换之前的最后一小时时,时间重叠。 ZonedDateTime类适应这种情况,而无法访问ZoneRules的OffsetDateTime和OffsetTime类则不适用。
ZonedDateTime
ZonedDateTime 类实际上将 LocalDateTime类与 ZoneId类组合在一起。它用于表示时区(区域/城市,例如Europe / Paris )的完整日期(年,月,日)和时间(小时,分钟,秒,纳秒)。
来自 `Flight `示例的以下代码定义了从旧金山飞往东京的航班起飞时间ZonedDateTime美国/洛杉矶时区。带有 ZoneSameInstant 和plusMinutes方法的用于创建ZonedDateTime的实例,该实例表示 650 分钟飞行后在东京的预计到达时间。ZoneRules.isDaylightSavings方法确定航班抵达东京时是否为夏令时。
DateTimeFormatter对象用于格式化ZonedDateTime实例以进行打印:
DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM d yyyy hh:mm a");// Leaving from San Francisco on July 20, 2013, at 7:30 p.m.LocalDateTime leaving = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);ZoneId leavingZone = ZoneId.of("America/Los_Angeles");ZonedDateTime departure = ZonedDateTime.of(leaving, leavingZone);try {String out1 = departure.format(format);System.out.printf("LEAVING: %s (%s)%n", out1, leavingZone);} catch (DateTimeException exc) {System.out.printf("%s can't be formatted!%n", departure);throw exc;}// Flight is 10 hours and 50 minutes, or 650 minutesZoneId arrivingZone = ZoneId.of("Asia/Tokyo");ZonedDateTime arrival = departure.withZoneSameInstant(arrivingZone).plusMinutes(650);try {String out2 = arrival.format(format);System.out.printf("ARRIVING: %s (%s)%n", out2, arrivingZone);} catch (DateTimeException exc) {System.out.printf("%s can't be formatted!%n", arrival);throw exc;}if (arrivingZone.getRules().isDaylightSavings(arrival.toInstant()))System.out.printf(" (%s daylight saving time will be in effect.)%n",arrivingZone);elseSystem.out.printf(" (%s standard time will be in effect.)%n",arrivingZone);
这会产生以下输出:
LEAVING: Jul 20 2013 07:30 PM (America/Los_Angeles)ARRIVING: Jul 21 2013 10:20 PM (Asia/Tokyo)(Asia/Tokyo standard time will be in effect.)
OffsetDateTime
OffsetDateTime 类实际上将 LocalDateTime类与 ZoneOffset类组合在一起。它用于表示完整日期(年,月,日)和时间(小时,分钟,秒,纳秒),偏离格林威治/ UTC 时间(+/-小时:分钟,例如+06: 00或-08:00 )。
以下示例使用OffsetDateTime和TemporalAdjuster.lastDay方法查找 2013 年 7 月的最后一个星期四。
// Find the last Thursday in July 2013.LocalDateTime localDate = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);ZoneOffset offset = ZoneOffset.of("-08:00");OffsetDateTime offsetDate = OffsetDateTime.of(localDate, offset);OffsetDateTime lastThursday =offsetDate.with(TemporalAdjusters.lastInMonth(DayOfWeek.THURSDAY));System.out.printf("The last Thursday in July 2013 is the %sth.%n",lastThursday.getDayOfMonth());
运行此代码的输出是:
The last Thursday in July 2013 is the 25th.
OffsetTime
OffsetTime 类实际上将 LocalTime类与 ZoneOffset类组合在一起。它用于表示时间(小时,分钟,秒,纳秒),偏离格林威治/ UTC 时间(+/-小时:分钟,例如+06:00或-08: 00 )。
OffsetTime类用于与OffsetDateTime类相同的情况,但不需要跟踪日期。
