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