Java ZonedDateTime 类
最后修改时间:2025 年 4 月 16 日
java.time.ZonedDateTime
类表示带时区的日期时间。它结合了 LocalDateTime 和 ZoneId 来处理时区规则。这个类是不可变的且线程安全的。
当时区上下文很重要时,使用 ZonedDateTime
。它会自动处理夏令时。该类提供高达纳秒的精度,并遵循 ISO-8601 日历系统。
ZonedDateTime 类概述
ZonedDateTime
提供了创建、操作和格式化日期时间值的方法。它可以在时区之间转换并处理夏令时。该类是 Java 8 中引入的现代日期时间 API 的一部分。
public final class ZonedDateTime implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable { public static ZonedDateTime now(); public static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone); public static ZonedDateTime parse(CharSequence text); public ZoneId getZone(); public ZonedDateTime withZoneSameInstant(ZoneId zone); public LocalDateTime toLocalDateTime(); public Instant toInstant(); public boolean isBefore(ChronoZonedDateTime<?> other); public boolean isAfter(ChronoZonedDateTime<?> other); }
上面的代码展示了 ZonedDateTime
的关键方法。这些方法允许进行时区感知的日期时间操作。该类会自动处理所有时区转换和夏令时调整。
创建 ZonedDateTime 对象
可以以多种方式创建 ZonedDateTime 对象。最常用的方法是使用 now
获取当前时间,以及使用工厂方法创建特定值。也支持从字符串解析。
package com.zetcode; import java.time.ZonedDateTime; import java.time.ZoneId; import java.time.LocalDateTime; public class Main { public static void main(String[] args) { // Current date-time with timezone ZonedDateTime now = ZonedDateTime.now(); System.out.println("Current ZonedDateTime: " + now); // Specific timezone ZonedDateTime parisTime = ZonedDateTime.now(ZoneId.of("Europe/Paris")); System.out.println("Paris time: " + parisTime); // From LocalDateTime LocalDateTime ldt = LocalDateTime.of(2025, 6, 15, 10, 30); ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.of("America/New_York")); System.out.println("From LocalDateTime: " + zdt); // From string ZonedDateTime parsed = ZonedDateTime.parse("2025-01-01T12:00:00+01:00[Europe/Berlin]"); System.out.println("Parsed from string: " + parsed); } }
此示例展示了创建 ZonedDateTime 对象的不同方法。输出包括日期时间信息和时区信息。请注意时区如何影响显示的日期时间值。
获取 ZonedDateTime 组件
ZonedDateTime 可以分解成它的组成部分,例如年、月和时区。这些值对于显示或进一步计算很有用。该类提供了所有组件的 getter 方法。
package com.zetcode; import java.time.ZonedDateTime; import java.time.ZoneId; public class Main { public static void main(String[] args) { ZonedDateTime zdt = ZonedDateTime.now(); // Get date and time components System.out.println("Year: " + zdt.getYear()); System.out.println("Month: " + zdt.getMonth()); System.out.println("Day: " + zdt.getDayOfMonth()); System.out.println("Hour: " + zdt.getHour()); System.out.println("Minute: " + zdt.getMinute()); // Get timezone information ZoneId zone = zdt.getZone(); System.out.println("Timezone: " + zone.getId()); // Get offset from UTC System.out.println("Offset: " + zdt.getOffset()); } }
此示例演示了如何从 ZonedDateTime 提取组件。时区信息包括区域 ID 和 UTC 偏移量。所有组件都反映了指定时区中的值。
转换时区
ZonedDateTime 可以在不同的时区之间转换,同时保留时间点。这对于在不同位置显示同一时刻很有用。转换会自动处理夏令时。
package com.zetcode; import java.time.ZonedDateTime; import java.time.ZoneId; public class Main { public static void main(String[] args) { ZonedDateTime nyTime = ZonedDateTime.now(ZoneId.of("America/New_York")); System.out.println("New York time: " + nyTime); // Convert to London time ZonedDateTime londonTime = nyTime.withZoneSameInstant(ZoneId.of("Europe/London")); System.out.println("London time: " + londonTime); // Convert to Tokyo time ZonedDateTime tokyoTime = nyTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo")); System.out.println("Tokyo time: " + tokyoTime); // Keep local time, change only timezone ZonedDateTime sameLocal = nyTime.withZoneSameLocal(ZoneId.of("Europe/Paris")); System.out.println("Same local time in Paris: " + sameLocal); } }
此示例显示了使用 ZonedDateTime 进行时区转换。withZoneSameInstant
方法更改时区,同时保持相同的时刻。withZoneSameLocal
保留本地时间值。
比较 ZonedDateTime
ZonedDateTime 对象可以按时间顺序进行比较。比较考虑了时间点和时区规则。这确保了跨时区的事件的准确排序。
package com.zetcode; import java.time.ZonedDateTime; import java.time.ZoneId; import java.time.Duration; public class Main { public static void main(String[] args) { ZonedDateTime nyTime = ZonedDateTime.now(ZoneId.of("America/New_York")); ZonedDateTime londonTime = nyTime.withZoneSameInstant(ZoneId.of("Europe/London")); ZonedDateTime futureTime = nyTime.plusHours(2); System.out.println("NY before London: " + nyTime.isBefore(londonTime)); System.out.println("NY after future: " + nyTime.isAfter(futureTime)); System.out.println("Compare NY and London: " + nyTime.compareTo(londonTime)); // Time difference between zones Duration offsetDiff = Duration.between(nyTime.toLocalTime(), londonTime.toLocalTime()); System.out.println("Time difference: " + offsetDiff.toHours() + " hours"); } }
此示例演示了比较 ZonedDateTime 对象。比较方法考虑了实际的时间点,而不仅仅是本地时间值。时间差计算显示了时区之间的当前偏移量。
使用夏令时
ZonedDateTime 自动处理夏令时转换。它根据时区规则调整时间值。这确保了全年正确的时间表示。
package com.zetcode; import java.time.ZonedDateTime; import java.time.ZoneId; import java.time.Month; public class Main { public static void main(String[] args) { ZoneId nyZone = ZoneId.of("America/New_York"); // Before DST transition (March 10, 2025 1:59 AM) ZonedDateTime beforeDST = ZonedDateTime.of(2025, 3, 10, 1, 59, 0, 0, nyZone); System.out.println("Before DST: " + beforeDST); // After DST transition (1 hour later) ZonedDateTime afterDST = beforeDST.plusHours(1); System.out.println("After DST: " + afterDST); // Check if DST is in effect System.out.println("Is DST: " + afterDST.getZone().getRules().isDaylightSavings(afterDST.toInstant())); // November DST end ZonedDateTime endDST = ZonedDateTime.of(2025, 11, 2, 1, 59, 0, 0, nyZone); System.out.println("Before DST end: " + endDST); System.out.println("After DST end: " + endDST.plusHours(1)); } }
此示例显示了 ZonedDateTime 处理夏令时转换。自动处理了春季和秋季的时间调整。可以检查任何特定时刻的 DST 状态。
转换为其他类型
ZonedDateTime 可以转换为其他日期时间类型,例如 LocalDateTime 或 Instant。当不再需要时区信息或使用旧版 API 时,这些转换很有用。
package com.zetcode; import java.time.ZonedDateTime; import java.time.LocalDateTime; import java.time.Instant; import java.time.OffsetDateTime; public class Main { public static void main(String[] args) { ZonedDateTime zdt = ZonedDateTime.now(); // Convert to LocalDateTime (loses timezone) LocalDateTime ldt = zdt.toLocalDateTime(); System.out.println("LocalDateTime: " + ldt); // Convert to Instant (UTC) Instant instant = zdt.toInstant(); System.out.println("Instant: " + instant); // Convert to OffsetDateTime (keeps offset but not zone ID) OffsetDateTime odt = zdt.toOffsetDateTime(); System.out.println("OffsetDateTime: " + odt); // Convert back to ZonedDateTime ZonedDateTime back = instant.atZone(zdt.getZone()); System.out.println("Back to ZonedDateTime: " + back); } }
此示例演示了 ZonedDateTime 和其他日期时间类型之间的转换。每次转换都有不同的目的,具体取决于是否需要时区、偏移量或 UTC 时间。可以重建原始的 ZonedDateTime。
来源
在本文中,我们介绍了 Java ZonedDateTime 类的基本方法和特性。理解这些概念对于在现代 Java 应用程序中准确处理时区至关重要。
作者
列出所有Java教程。