Java ZoneRules 类
最后修改时间:2025 年 4 月 16 日
java.time.zone.ZoneRules
类表示时区的一组规则。它定义了特定区域的 UTC 偏移量随时间的变化。ZoneRules 处理夏令时转换和历史变动。
ZoneRules
是不可变的且线程安全的。它通常从 ZoneId
获取,并提供有关时区行为的详细信息。该类包含特定时区的所有转换规则。
ZoneRules 类概述
ZoneRules
提供了查询偏移量变化、转换和夏令时信息的方法。关键操作包括检查固定偏移量、获取当前规则以及检查历史转换。
public final class ZoneRules implements Serializable { public boolean isFixedOffset(); public ZoneOffset getOffset(Instant instant); public ZoneOffset getOffset(LocalDateTime localDateTime); public List<ZoneOffsetTransition> getTransitions(); public List<ZoneOffsetTransitionRule> getTransitionRules(); public boolean isDaylightSavings(Instant instant); public Duration getDaylightSavings(Instant instant); public boolean isValidOffset(LocalDateTime localDateTime, ZoneOffset offset); }
以上代码显示了 ZoneRules
提供的关键方法。这些方法允许检查特定时刻的时区行为。该类处理固定偏移量时区和具有夏令时的时区。
获取 ZoneRules
ZoneRules 对象通常通过 ZoneId 实例获取。系统时区数据库提供标准时区的规则。您也可以根据需要创建自定义规则。
package com.zetcode; import java.time.ZoneId; import java.time.zone.ZoneRules; public class Main { public static void main(String[] args) { // Get rules for system default timezone ZoneRules defaultRules = ZoneId.systemDefault().getRules(); System.out.println("System default rules: " + defaultRules); // Get rules for specific timezone ZoneRules parisRules = ZoneId.of("Europe/Paris").getRules(); System.out.println("Paris rules: " + parisRules); // Check if fixed offset System.out.println("Is fixed offset: " + parisRules.isFixedOffset()); // Get rules for UTC ZoneRules utcRules = ZoneId.of("UTC").getRules(); System.out.println("UTC rules: " + utcRules); System.out.println("UTC fixed offset: " + utcRules.isFixedOffset()); } }
此示例演示了如何为不同的时区获取 ZoneRules。输出显示 UTC 具有固定偏移量规则,而巴黎具有夏令时转换。系统默认规则取决于 JVM 的环境。
获取 Instant 的偏移量
ZoneRules 可以确定特定时刻的 UTC 偏移量。这对于在本地时间和 UTC 之间进行转换至关重要。该方法考虑了所有历史转换。
package com.zetcode; import java.time.Instant; import java.time.ZoneId; import java.time.zone.ZoneRules; public class Main { public static void main(String[] args) { ZoneRules nyRules = ZoneId.of("America/New_York").getRules(); // Current offset Instant now = Instant.now(); System.out.println("Current NY offset: " + nyRules.getOffset(now)); // Winter time Instant winter = Instant.parse("2025-01-15T12:00:00Z"); System.out.println("Winter NY offset: " + nyRules.getOffset(winter)); // Summer time Instant summer = Instant.parse("2025-06-15T12:00:00Z"); System.out.println("Summer NY offset: " + nyRules.getOffset(summer)); // Historical change (before 2007 rules) Instant oldDate = Instant.parse("2000-06-15T12:00:00Z"); System.out.println("2000 summer offset: " + nyRules.getOffset(oldDate)); } }
此示例显示了如何获取纽约不同时刻的 UTC 偏移量。输出演示了夏令时变化和历史规则差异。该方法自动处理所有转换。
检查夏令时
ZoneRules 提供了方法来检查特定时刻是否生效夏令时。它还可以返回夏令时调整量。这些方法对于时区感知计算很有用。
package com.zetcode; import java.time.Instant; import java.time.ZoneId; import java.time.zone.ZoneRules; public class Main { public static void main(String[] args) { ZoneRules londonRules = ZoneId.of("Europe/London").getRules(); Instant winter = Instant.parse("2025-01-15T12:00:00Z"); Instant summer = Instant.parse("2025-06-15T12:00:00Z"); System.out.println("Winter DST: " + londonRules.isDaylightSavings(winter)); System.out.println("Summer DST: " + londonRules.isDaylightSavings(summer)); System.out.println("Winter DST amount: " + londonRules.getDaylightSavings(winter)); System.out.println("Summer DST amount: " + londonRules.getDaylightSavings(summer)); // Transition moment Instant transition = Instant.parse("2025-03-30T01:00:00Z"); System.out.println("Transition moment DST: " + londonRules.isDaylightSavings(transition)); } }
此示例检查伦敦在不同时刻的夏令时状态。getDaylightSavings
方法返回 DST 调整的持续时间。请注意,转换时刻的处理取决于确切的规则。
检查转换
ZoneRules 提供了访问时区所有历史和未来转换规则的权限。这些转换代表了 UTC 偏移量变化的时刻,通常用于夏令时。
package com.zetcode; import java.time.ZoneId; import java.time.zone.ZoneRules; import java.time.zone.ZoneOffsetTransition; public class Main { public static void main(String[] args) { ZoneRules tokyoRules = ZoneId.of("Asia/Tokyo").getRules(); // Tokyo has no DST, so transitions list is empty System.out.println("Tokyo transitions: " + tokyoRules.getTransitions().size()); ZoneRules chicagoRules = ZoneId.of("America/Chicago").getRules(); // Get all defined transitions System.out.println("\nChicago transitions:"); for (ZoneOffsetTransition trans : chicagoRules.getTransitions()) { System.out.println(trans); } // Get transition rules (recurring patterns) System.out.println("\nChicago transition rules:"); chicagoRules.getTransitionRules().forEach(System.out::println); } }
此示例检查东京(无 DST)和芝加哥(有 DST)的转换。getTransitions
方法返回历史变化,而 getTransitionRules
提供重复模式。东京未显示任何转换,因为它不遵守 DST。
验证本地日期时间偏移量
ZoneRules 可以验证特定的本地日期时间组合和偏移量对于该时区是否有效。这对于在 DST 转换期间检查不明确或无效的时间很有用。
package com.zetcode; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.zone.ZoneRules; public class Main { public static void main(String[] args) { ZoneRules nyRules = ZoneId.of("America/New_York").getRules(); // Normal time LocalDateTime normalTime = LocalDateTime.of(2025, 1, 15, 12, 0); System.out.println("Normal time valid: " + nyRules.isValidOffset(normalTime, ZoneOffset.ofHours(-5))); // DST transition forward (2 AM becomes 3 AM) LocalDateTime springForward = LocalDateTime.of(2025, 3, 9, 2, 30); System.out.println("Spring forward valid: " + nyRules.isValidOffset(springForward, ZoneOffset.ofHours(-5))); System.out.println("Spring forward valid DST: " + nyRules.isValidOffset(springForward, ZoneOffset.ofHours(-4))); // DST transition backward (ambiguous time) LocalDateTime fallBack = LocalDateTime.of(2025, 11, 2, 1, 30); System.out.println("Fall back valid standard: " + nyRules.isValidOffset(fallBack, ZoneOffset.ofHours(-5))); System.out.println("Fall back valid DST: " + nyRules.isValidOffset(fallBack, ZoneOffset.ofHours(-4))); } }
此示例验证正常时间和 DST 转换期间的偏移量组合。春季前移转换会创建一个无效时间(凌晨 2:30 不存在)。秋季后退转换会产生歧义(凌晨 1:30 出现两次)。
使用固定偏移量时区
某些时区具有永不改变的固定偏移量。ZoneRules 为这些情况提供了特殊处理,其行为比具有转换的时区更简单。
package com.zetcode; import java.time.Instant; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.zone.ZoneRules; public class Main { public static void main(String[] args) { // Fixed offset zone ZoneOffset fixedOffset = ZoneOffset.ofHours(3); ZoneRules fixedRules = fixedOffset.getRules(); System.out.println("Is fixed offset: " + fixedRules.isFixedOffset()); // Offset is always the same Instant now = Instant.now(); System.out.println("Current offset: " + fixedRules.getOffset(now)); Instant future = now.plusSeconds(3600 * 24 * 365 * 10); // 10 years later System.out.println("Future offset: " + fixedRules.getOffset(future)); // No transitions System.out.println("Transitions: " + fixedRules.getTransitions().size()); System.out.println("Transition rules: " + fixedRules.getTransitionRules().size()); // Always no DST System.out.println("DST active: " + fixedRules.isDaylightSavings(now)); } }
此示例演示了固定偏移量时区的行为。无论查询的时刻如何,偏移量永远不会改变。对于固定偏移量时区,没有转换,夏令时也永远不会生效。
来源
在本文中,我们介绍了 Java ZoneRules 类的基本方法和特性。了解这些概念对于在现代 Java 应用程序中进行精确的时区处理至关重要。
作者
列出所有Java教程。