Java ZoneRulesProvider Class
Last modified: April 16, 2025
The java.time.zone.ZoneRulesProvider
class provides time-zone rules
to the system. It acts as a service provider for time-zone rules. The class is
abstract and must be subclassed to provide custom time-zone rules.
ZoneRulesProvider
manages the available time-zone IDs and their
rules. The default provider uses the IANA Time Zone Database. Multiple providers
can be registered, with later registrations taking precedence.
ZoneRulesProvider Class Overview
ZoneRulesProvider
provides methods to register providers and access
time-zone rules. Key operations include getting available zone IDs and rules for
specific zones. The class is thread-safe and designed for extension.
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); }
The code above shows key methods of ZoneRulesProvider
. Abstract
methods must be implemented by concrete providers. The class supports versioned
time-zone rules through the provideVersions
method.
Getting Available Time-Zone IDs
The getAvailableZoneIds
method returns all available time-zone IDs
from all registered providers. This is useful for discovering what time-zones
are supported by the system.
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); } }
This example retrieves all available time-zone IDs and prints the total count. It then displays the first five zone IDs. The output will vary based on the registered providers and Java version.
Getting Rules for a Specific Time-Zone
The getRules
method retrieves the rules for a specific time-zone.
These rules include transitions, offsets, and daylight savings information.
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())); } }
This example retrieves the rules for New York timezone and prints some key properties. The output shows whether the zone has a fixed offset and current daylight savings status.
Creating a Custom ZoneRulesProvider
Custom providers can be created by extending ZoneRulesProvider
.
This allows adding support for custom time-zone rules not in the IANA database.
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())); } }
This example creates a custom provider for a simple fixed-offset timezone. The provider is registered and then used to get rules for the custom zone. Note that real-world providers would handle more complex scenarios.
Registering Multiple Providers
Multiple providers can be registered with different priorities. Higher priority providers are checked first when resolving time-zone rules.
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 } }
This example demonstrates provider priority. The high priority provider's rules take precedence. The output shows the offset from the higher priority provider.
Checking Provider Registration
While there's no direct API to list registered providers, we can infer their presence by checking available zone IDs and rule behavior.
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; } } }
This example checks provider registration indirectly by comparing zone ID sets. It shows how to verify that a custom provider has been successfully registered.
Handling Time-Zone Versions
The provideVersions
method allows providers to support multiple
versions of time-zone rules. This is useful for historical accuracy.
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()); } }
This example creates a provider with versioned rules. The provideVersions
method returns different rules for different years. Note that the standard Java
API doesn't directly use these versions.
Source
Java ZoneRulesProvider Class Documentation
In this article, we've covered the essential methods and features of the Java ZoneRulesProvider class. Understanding these concepts is crucial for advanced time-zone handling in Java applications.
Author
List all Java tutorials.