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教程。