426. Java 日期时间 API - Time Zone 与 Offset

0 阅读2分钟

426. Java 日期时间 API - Time Zone 与 Offset

1. 什么是 Time Zone(时区)和 Offset(偏移量)?

  • Time Zone(时区) 👉 地球上使用同一标准时间的区域。
    • 每个时区都有一个 标识符(identifier),常见的格式是 Region/City,比如:Asia/Tokyo
    • 时区会和 格林尼治时间(UTC/GMT) 有一定的偏移量(offset)。
    • ✅ 例如:东京的偏移量是 +09:00,也就是比 UTC 快 9 小时。
  • Offset(偏移量) 👉 相对于 UTC 的具体时间差。
    • 通常是整点(+08:00、-05:00),但有些地区会以 30 分钟甚至 45 分钟为单位来偏移。

2. Java 中的 ZoneId 和 ZoneOffset

Java Date-Time API 提供了两个核心类:

  1. ZoneId
    • 用来表示一个具体的时区 ID(例如 "Asia/Shanghai""America/New_York")。
    • 它包含了时区的转换规则,可以把一个 Instant(时间戳)转换成当地时间 LocalDateTime
  2. ZoneOffset
    • 表示相对于 UTC 的具体偏移量,例如 +09:00-04:30
    • 直接体现的是数值差,而不是时区名称。

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. 小结 🎯

  1. ZoneId 👉 用来表示 地区性的时区,带有完整的历史和夏令时规则。
    • 例子:ZoneId.of("Asia/Shanghai")
  2. ZoneOffset 👉 只表示 相对于 UTC 的偏移量,不考虑夏令时。
    • 例子:ZoneOffset.ofHoursMinutes(5, 30) 👉 +05:30
  3. 有些地区的时区并不是整点,比如:
    • 印度(Asia/Kolkata) 👉 +05:30
    • 尼泊尔(Asia/Kathmandu) 👉 +05:45
    • 纽芬兰(Canada/Newfoundland) 👉 -02:30

6. 课堂互动 💡

你可以问学员几个问题来加深理解:

  1. 问题:如果我想要得到上海当前的本地时间,应该用哪个类? ✅ 答案:ZoneId.of("Asia/Shanghai") + ZonedDateTime
  2. 问题:如果我只关心某地比 UTC 快多少小时,用哪个类? ✅ 答案:ZoneOffset