426. Java 日期时间 API - Time Zone 与 Offset
1. 什么是 Time Zone(时区)和 Offset(偏移量)?
- Time Zone(时区) 👉 地球上使用同一标准时间的区域。
- 每个时区都有一个 标识符(identifier),常见的格式是
Region/City,比如:Asia/Tokyo。 - 时区会和 格林尼治时间(UTC/GMT) 有一定的偏移量(offset)。
- ✅ 例如:东京的偏移量是
+09:00,也就是比 UTC 快 9 小时。
- 每个时区都有一个 标识符(identifier),常见的格式是
- Offset(偏移量) 👉 相对于 UTC 的具体时间差。
- 通常是整点(+08:00、-05:00),但有些地区会以 30 分钟甚至 45 分钟为单位来偏移。
2. Java 中的 ZoneId 和 ZoneOffset
Java Date-Time API 提供了两个核心类:
ZoneId- 用来表示一个具体的时区 ID(例如
"Asia/Shanghai"、"America/New_York")。 - 它包含了时区的转换规则,可以把一个
Instant(时间戳)转换成当地时间LocalDateTime。
- 用来表示一个具体的时区 ID(例如
ZoneOffset- 表示相对于 UTC 的具体偏移量,例如
+09:00、-04:30。 - 直接体现的是数值差,而不是时区名称。
- 表示相对于 UTC 的具体偏移量,例如
3. 示例代码:找出非整点时区 ⏱️
下面的代码会遍历所有时区,输出那些 偏移量不是整点 的时区(比如 +05:30、+05:45)。
import java.time.*;
import java.util.*;
public class ZoneExample {
public static void main(String[] args) {
// 获取所有可用的时区 ID
Set<String> allZones = ZoneId.getAvailableZoneIds();
LocalDateTime dt = LocalDateTime.now();
// 将 Set 转成 List 并排序
List<String> zoneList = new ArrayList<>(allZones);
Collections.sort(zoneList);
for (String zoneId : zoneList) {
ZoneId zone = ZoneId.of(zoneId);
ZonedDateTime zdt = dt.atZone(zone);
ZoneOffset offset = zdt.getOffset();
// 判断偏移量是否为整小时
int secondsOfHour = offset.getTotalSeconds() % (60 * 60);
if (secondsOfHour != 0) {
System.out.printf("%35s %10s%n", zoneId, offset);
}
}
}
}
4. 示例输出(部分结果)📋
America/Caracas -04:30
America/St_Johns -02:30
Asia/Kathmandu +05:45
Australia/Adelaide +09:30
Pacific/Chatham +12:45
5. 小结 🎯
ZoneId👉 用来表示 地区性的时区,带有完整的历史和夏令时规则。- 例子:
ZoneId.of("Asia/Shanghai")
- 例子:
ZoneOffset👉 只表示 相对于 UTC 的偏移量,不考虑夏令时。- 例子:
ZoneOffset.ofHoursMinutes(5, 30)👉+05:30
- 例子:
- 有些地区的时区并不是整点,比如:
- 印度(
Asia/Kolkata) 👉+05:30 - 尼泊尔(
Asia/Kathmandu) 👉+05:45 - 纽芬兰(
Canada/Newfoundland) 👉-02:30
- 印度(
6. 课堂互动 💡
你可以问学员几个问题来加深理解:
- 问题:如果我想要得到上海当前的本地时间,应该用哪个类?
✅ 答案:
ZoneId.of("Asia/Shanghai")+ZonedDateTime - 问题:如果我只关心某地比 UTC 快多少小时,用哪个类?
✅ 答案:
ZoneOffset