Java ZoneRulesProvider 类
最后修改时间:2025 年 4 月 16 日
java.time.zone.ZoneRulesProvider
类为系统提供时区规则。它充当时区规则的服务提供者。该类是抽象的,必须被子类化以提供自定义时区规则。
ZoneRulesProvider
管理可用的时区 ID 及其规则。默认提供者使用 IANA 时区数据库。可以注册多个提供者,后注册的提供者具有优先权。
ZoneRulesProvider 类概述
ZoneRulesProvider
提供注册提供者和访问时区规则的方法。关键操作包括获取可用的时区 ID 和特定区域的规则。该类是线程安全的,并且设计用于扩展。
public abstract class ZoneRulesProvider { public static Set<String> getAvailableZoneIds(); public static ZoneRules getRules(String zoneId, boolean forCaching); public static void registerProvider(ZoneRulesProvider provider); public static void registerProvider(ZoneRulesProvider provider, int priority); protected abstract Set<String> provideZoneIds(); protected abstract ZoneRules provideRules(String zoneId, boolean forCaching); protected abstract NavigableMap<String, ZoneRules> provideVersions(String zoneId); }
上面的代码显示了 ZoneRulesProvider
的关键方法。抽象方法必须由具体提供者实现。该类通过 provideVersions
方法支持版本化的时区规则。
获取可用的时区 ID
getAvailableZoneIds
方法从所有注册的提供者返回所有可用的时区 ID。这对于发现系统支持哪些时区很有用。
package com.zetcode; import java.time.zone.ZoneRulesProvider; import java.util.Set; public class Main { public static void main(String[] args) { Set<String> zoneIds = ZoneRulesProvider.getAvailableZoneIds(); System.out.println("Total zones available: " + zoneIds.size()); System.out.println("First 5 zones:"); zoneIds.stream() .limit(5) .forEach(System.out::println); } }
此示例检索所有可用的时区 ID 并打印总数。然后它显示前五个时区 ID。输出将根据注册的提供者和 Java 版本而有所不同。
获取特定时区的规则
getRules
方法检索特定时区的规则。这些规则包括转换、偏移量和夏令时信息。
package com.zetcode; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesProvider; public class Main { public static void main(String[] args) { String zoneId = "America/New_York"; ZoneRules rules = ZoneRulesProvider.getRules(zoneId, false); System.out.println("Rules for " + zoneId + ":"); System.out.println("Fixed offset: " + rules.isFixedOffset()); System.out.println("Standard offset: " + rules.getStandardOffset( java.time.Instant.now())); System.out.println("Daylight savings active now: " + rules.isDaylightSavings(java.time.Instant.now())); } }
此示例检索纽约时区的规则并打印一些关键属性。输出显示该时区是否具有固定偏移量和当前的夏令时状态。
创建自定义 ZoneRulesProvider
可以通过扩展 ZoneRulesProvider
来创建自定义提供者。这允许添加对 IANA 数据库中不存在的自定义时区规则的支持。
package com.zetcode; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesProvider; import java.util.Collections; import java.util.NavigableMap; import java.util.Set; import java.time.Instant; import java.time.ZoneOffset; public class CustomZoneProvider extends ZoneRulesProvider { @Override protected Set<String> provideZoneIds() { return Collections.singleton("CUSTOM/UTC+2"); } @Override protected ZoneRules provideRules(String zoneId, boolean forCaching) { if ("CUSTOM/UTC+2".equals(zoneId)) { return ZoneRules.of(ZoneOffset.ofHours(2)); } return null; } @Override protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) { return null; } } public class Main { public static void main(String[] args) { ZoneRulesProvider.registerProvider(new CustomZoneProvider()); ZoneRules rules = ZoneRulesProvider.getRules("CUSTOM/UTC+2", false); System.out.println("Custom zone offset: " + rules.getOffset(Instant.now())); } }
此示例为简单的固定偏移量时区创建自定义提供者。提供者已注册,然后用于获取自定义区域的规则。请注意,现实世界的提供者将处理更复杂的场景。
注册多个提供者
可以注册具有不同优先级的多个提供者。在解析时区规则时,首先检查较高优先级的提供者。
package com.zetcode; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesProvider; import java.util.Collections; import java.util.NavigableMap; import java.util.Set; import java.time.Instant; import java.time.ZoneOffset; class HighPriorityProvider extends ZoneRulesProvider { @Override protected Set<String> provideZoneIds() { return Collections.singleton("PRIORITY/TEST"); } @Override protected ZoneRules provideRules(String zoneId, boolean forCaching) { return ZoneRules.of(ZoneOffset.ofHours(3)); } @Override protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) { return null; } } class LowPriorityProvider extends ZoneRulesProvider { @Override protected Set<String> provideZoneIds() { return Collections.singleton("PRIORITY/TEST"); } @Override protected ZoneRules provideRules(String zoneId, boolean forCaching) { return ZoneRules.of(ZoneOffset.ofHours(4)); } @Override protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) { return null; } } public class Main { public static void main(String[] args) { ZoneRulesProvider.registerProvider(new LowPriorityProvider(), 1); ZoneRulesProvider.registerProvider(new HighPriorityProvider(), 2); ZoneRules rules = ZoneRulesProvider.getRules("PRIORITY/TEST", false); System.out.println("Effective offset: " + rules.getOffset(Instant.now())); // Will show +03:00 } }
此示例演示提供者优先级。高优先级提供者的规则优先。输出显示来自较高优先级提供者的偏移量。
检查提供者注册
虽然没有直接的 API 可以列出已注册的提供者,但我们可以通过检查可用的时区 ID 和规则行为来推断它们的存在。
package com.zetcode; import java.time.zone.ZoneRulesProvider; import java.util.Set; public class Main { public static void main(String[] args) { // Count zones before registration Set<String> beforeIds = ZoneRulesProvider.getAvailableZoneIds(); System.out.println("Zones before: " + beforeIds.size()); // Register a custom provider ZoneRulesProvider.registerProvider(new CustomZoneProvider()); // Count zones after registration Set<String> afterIds = ZoneRulesProvider.getAvailableZoneIds(); System.out.println("Zones after: " + afterIds.size()); // Check if our custom zone is available if (afterIds.contains("CUSTOM/UTC+2")) { System.out.println("Custom provider is active"); } } static class CustomZoneProvider extends ZoneRulesProvider { @Override protected Set<String> provideZoneIds() { return Set.of("CUSTOM/UTC+2"); } @Override protected ZoneRules provideRules(String zoneId, boolean forCaching) { return null; } @Override protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) { return null; } } }
此示例通过比较时区 ID 集间接检查提供者注册。它显示了如何验证自定义提供者是否已成功注册。
处理时区版本
provideVersions
方法允许提供者支持多个时区规则版本。这对于历史准确性很有用。
package com.zetcode; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesProvider; import java.util.NavigableMap; import java.util.Set; import java.util.TreeMap; import java.time.Instant; import java.time.ZoneOffset; public class VersionedZoneProvider extends ZoneRulesProvider { @Override protected Set<String> provideZoneIds() { return Set.of("VERSIONED/TEST"); } @Override protected ZoneRules provideRules(String zoneId, boolean forCaching) { return ZoneRules.of(ZoneOffset.ofHours(2)); } @Override protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) { if ("VERSIONED/TEST".equals(zoneId)) { NavigableMap<String, ZoneRules> versions = new TreeMap<>(); versions.put("2023", ZoneRules.of(ZoneOffset.ofHours(2))); versions.put("2024", ZoneRules.of(ZoneOffset.ofHours(3))); return versions; } return null; } } public class Main { public static void main(String[] args) { ZoneRulesProvider.registerProvider(new VersionedZoneProvider()); NavigableMap<String, ZoneRules> versions = ZoneRulesProvider.getVersions("VERSIONED/TEST"); System.out.println("Available versions: " + versions.keySet()); } }
此示例创建了一个具有版本化规则的提供者。provideVersions
方法为不同的年份返回不同的规则。请注意,标准的 Java API 不直接使用这些版本。
来源
在本文中,我们介绍了 Java ZoneRulesProvider 类的基本方法和特性。理解这些概念对于 Java 应用程序中的高级时区处理至关重要。
作者
列出所有Java教程。