NAME
Time::Keeper::Zone - the time zones of the IANA database, compiled in
VERSION
Version 0.05
SYNOPSIS
use Time::Keeper::Zone;
my @zones = Time::Keeper::Zone->names;
my %links = Time::Keeper::Zone->links;
Time::Keeper::Zone->is_valid('europe/london'); # true
Time::Keeper::Zone->name('europe/london'); # Europe/London
Time::Keeper::Zone->canonical_name('US/Eastern'); # America/New_York
Time::Keeper::Zone->local_name; # this machine's zone
Time::Keeper::Zone->tzdata_version; # 2026e
my %countries = Time::Keeper::Zone->countries;
my @zones_gb = Time::Keeper::Zone->zones_for_country('GB');
Time::Keeper::Zone->windows_zone('GMT Standard Time'); # Europe/London
Time::Keeper::Zone->windows_name('Europe/London'); # GMT Standard Time
Time::Keeper::Zone->country_of('Europe/London'); # GB
my @changes = Time::Keeper::Zone->transitions('Europe/London', $from, $to);
my $next = Time::Keeper::Zone->next_transition('Europe/London', time);
my ($offset, $is_dst, $abbr) = Time::Keeper::Zone->offset_at('Europe/London', time);
Time::Keeper::Zone->standard_offset_at('Europe/London', time); # 0
Time::Keeper::Zone->has_dst('Asia/Tokyo', 2026); # false
DESCRIPTION
Time::Keeper::Zone holds the time zones that Time::Keeper uses. It is a dist of its own so that a new release of the IANA time zone database is a new release of this dist alone, and Time::Keeper itself does not change.
The zone data is compiled into the module. The system's own zone files are never read, so every machine gives the same answer for the same version of this dist.
Time::Keeper loads this module the first time a named zone is asked for. A program that works only in UTC or in fixed offsets never loads it.
A zone here is a name, not an object. Times in a zone are asked of Time::Keeper; this module answers questions about the zones themselves. Every method is a class method.
Names are matched without regard to case: europe/london is Europe/London. A link is an older or alternative name for a zone, such as US/Eastern for America/New_York; it follows that zone's rules exactly, and keeps its own name.
THE TIME ZONE DATABASE
This release carries the IANA time zone database's release 2026e, which "tzdata_version" also gives. IANA publishes several releases a year, whenever a country changes its clocks, often at short notice; a new one is a new release of this dist, and of this dist alone. Upgrading it is all a program needs to know of a change.
The system's zone files are never read. They are a different release on every machine, sometimes years old, sometimes missing (a minimal container, Windows), and reading them is file I/O on the first use of every zone. Compiled in, the data is the same on every machine for the same version of this dist, it is checked by this dist's tests, and finding a zone costs nothing.
The database's own build is compiled, as zic builds it by default: the history of zones before 1970 that IANA keeps apart, in its backzone file, is not included, as DateTime::TimeZone leaves it out too.
METHODS
names
Every zone's name, in order. Links are not included: see "links".
links
Every link, as a list of pairs: the link's name, then the name of the zone it follows. Assign it to a hash.
is_valid($name)
True if $name is a zone or a link, in any case.
name($name)
$name as the database spells it, or undef if it is not a zone or link. A link gives back its own name.
canonical_name($name)
The zone $name follows: the zone itself, or for a link the zone it leads to. Undef if it is neither.
local_name
The name of this machine's zone. It comes from the TZ environment variable if that names a zone (: before the name and a path ending in zoneinfo/Area/City are both understood, and an empty TZ means UTC), then from the name /etc/localtime links to, then /etc/timezone, then /etc/sysconfig/clock, and on Windows from the system's time zone key name mapped as windows_zone maps it. When none of them names a zone it is Etc/UTC. Only names are read: the system's own zone files never are.
tzdata_version
The release of the IANA time zone database compiled in, such as 2026e.
countries
Every country with a zone, as pairs of its ISO 3166 code and its name.
zones_for_country($code)
The zones a country uses, from the database's zone.tab, given its two-letter code in any case. A country whose clocks follow another's still has its own zone here: Norway's is Europe/Oslo. An empty list for a code that is not there.
windows_zone($windows_name)
The zone a Windows time zone name means, such as Europe/London for GMT Standard Time, from CLDR's table. Undef for a name it does not know.
windows_name($name)
The Windows time zone name of the zone $name follows, such as GMT Standard Time for Europe/London: the reverse of windows_zone. Undef for a zone Windows has no name of its own for, such as America/Detroit, and for a name that is not a zone or link.
country_of($name)
The ISO 3166 code of the country $name belongs to, such as GB for Europe/London: the reverse of zones_for_country. A link the database's zone.tab lists has its own country (Europe/Oslo is NO); any other link has its zone's (US/Eastern is US). Undef for a zone of no country, such as Etc/UTC, and for a name that is not a zone or link.
TRANSITIONS
A transition is an instant at which a zone's offset, its DST flag or its abbreviation changes. A change of abbreviation alone is one, and is listed: the offset before and after it are then the same.
The methods below take times as epoch seconds (seconds since 1970-01-01T00:00:00 UTC, leap seconds not counted), and a fraction counts as the second it falls in. They croak for a name that is not a zone or a link. Past a zone's last transition in the database, its rule for the future (a POSIX TZ string) gives every later transition, for any year.
A zone with a fixed offset, such as Etc/GMT+5, has no transitions.
transitions($name, $from, $to)
Each transition from $from to $to, both included, as a list of array references:
[ $epoch, $offset_before, $offset_after, $abbreviation_after, $is_dst_after ]
Offsets are seconds east of UTC, and $is_dst_after is 1 or 0. Croaks if $to is before $from or more than 1,000 years (of 365.25 days) after it.
for my $t (Time::Keeper::Zone->transitions('Europe/London', $from, $to)) {
my ($at, $before, $after, $abbr, $is_dst) = @$t;
...
}
next_transition($name, $epoch)
The first transition after $epoch, as epoch seconds, or undef if the zone never changes again.
previous_transition($name, $epoch)
The last transition before $epoch, or undef if there is none.
offset_at($name, $epoch)
In list context the zone's offset in seconds east of UTC at $epoch, 1 or 0 for whether it is daylight time, and the abbreviation in use:
my ($offset, $is_dst, $abbr) = Time::Keeper::Zone->offset_at('Europe/London', $epoch);
In scalar context the offset alone.
standard_offset_at($name, $epoch)
The offset of the zone's standard time at $epoch, in seconds east of UTC: during summer time, the offset it is an hour ahead of.
This is what the database's types say is standard, which is not always what the clocks are called. Europe/Dublin's standard time is Irish Standard Time, +01:00, all year: the database has GMT in winter as its daylight time, an hour behind. A zone in daylight time with no standard time since gives the standard offset it last had.
has_dst($name, $year)
True if the DST flag changes during $year, as the zone's own clocks count the year: London in 2026 does, Tokyo and Kolkata do not.
AUTHOR
LNATION <email@lnation.org>
BUGS
Please report any bugs or feature requests to bug-time-keeper-zone at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Time-Keeper-Zone.
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)