created: 2022-07-23T13:11:07+08:00
updated: 2022-07-23T14:17:40+08:00
tag:
- DateTimeAPI
- DateTimeAPI/ZonedDateTime
- DateTimeAPI/OffsetDateTime
- DateTimeAPI/OffsetTime
Time Zone and Offset
时区是使用相同标准时间的地球区域。每个时区由一个标识符描述,通常具有区域/城市(Asia/Tokyo)格式和 Greenwich/UTC 时间的偏移量。例如,东京的偏移量是 +09:00。
The ZoneId and ZoneOffset Classes
Date-Time API 提供了两个类用于指定时区或偏移量:
-
ZoneId
指定时区标识符并提供在Instant
和LocalDateTime
之间转换的规则。 -
ZoneOffset
指定与 Greenwich/UTC 时间的时区偏移量。
与 Greenwich/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<>(allZones).sort();
for (String zone : zoneList) {
ZoneId zone = ZoneId.of(zone);
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);
}
}
result
America/Caracas -04:30
America/St_Johns -02:30
Asia/Calcutta +05:30
Asia/Colombo +05:30
Asia/Kabul +04:30
Asia/Kathmandu +05:45
Asia/Katmandu +05:45
Asia/Kolkata +05:30
Asia/Rangoon +06:30
Asia/Tehran +04:30
Australia/Adelaide +09:30
Australia/Broken_Hill +09:30
Australia/Darwin +09:30
Australia/Eucla +08:45
Australia/LHI +10:30
Australia/Lord_Howe +10:30
Australia/North +09:30
Australia/South +09:30
Australia/Yancowinna +09:30
Canada/Newfoundland -02:30
Indian/Cocos +06:30
Iran +04:30
NZ-CHAT +12:45
Pacific/Chatham +12:45
Pacific/Marquesas -09:30
Pacific/Norfolk +11:30
The Date Time Classes
Date-Time API 提供了三个使用时区的基于时间的类:
-
ZonedDateTime
处理具有相应时区的日期和时间,该时区与 Greenwich/UTC 有时区偏移。 -
OffsetDateTime
处理具有相对于 Greenwich/UTC 的相应时区偏移的日期和时间,没有时区 ID。 -
OffsetTime
处理时间与 Greenwich/UTC 的相应时区偏移量,没有时区 ID。
The ZonedDateTime Class
ZonedDateTime
类实际上结合了 LocalDateTime
类和 ZoneId
类。
example
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 minutes
ZoneId 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);
} else{
System.out.printf(" (%s standard time will be in effect.)%n",
arrivingZone);
}
result
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.)
The OffsetDateTime Class
实际上,OffsetDateTime
类将 LocalDateTime
类与 ZoneOffset
类结合在一起。
example
// 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());
result
The last Thursday in July 2013 is the 25th.
The OffsetTime Class
实际上,OffsetTime
类将 LocalTime
类与 ZoneOffset
类结合在一起。
OffsetTime
类在与 OffsetDateTime
类相同的情况下使用,但在不需要跟踪日期时。
[[Instant]]