NAME
Time::OlsonTZ::Clustered - Olson time zone clusters based on similar
offset and DST changes
VERSION
version 0.001
SYNOPSIS
use Time::OlsonTZ::Clustered ':all';
say $_->timezone_name for @{ primary_zones('US') };
# Pacific/Honolulu
# America/Adak
# America/Anchorage
# America/Los_Angeles
# America/Metlakatla
# America/Denver
# America/Phoenix
# America/Chicago
# America/New_York
say find_primary("America/Indiana/Indianapolis");
# America/New_York
DESCRIPTION
There are over 400 Olson time zone names (e.g. "America/New_York")
describing current and historical offset and daylight-savings behavior.
While this is essential for accurate calculations involving times in the
past, it is an overwhelming list to present as part of a user experience
current behavior is relevant. (E.g. "Choose your time zone")
For example, China has had only one official time (UTC+8) since 1949,
but there are five Olson time zones corresponding to historical
districts:
Asia/Shanghai
Asia/Chongqing
Asia/Kashgar
Asia/Urumqi
Asia/Harbin
When presenting a list of time zone choices, there are many situations
in which it is sufficient to present "Asia/Shanghai" for China.
Likewise, the United States has consolidated some of its historically
fragmented time zone observance. Instead of asking someone if they are
in "America/Indiana/Indianapolis", it is sufficient to ask them to pick
"America/New_York" (a.k.a. "US Eastern Time").
This module provides a pre-calculated clustering the 400+ Olson time
zones by country and by time observance behavior, allowing a
consolidated list of "primary zones" to be offered for each country.
The clustering was developed using the following heuristics and
modifications:
* For each country, cluster time zones by observance behavior
* Zones cluster together if they have the same UTC offset at local
noon for the next 365 days
* If a cluster contains multiple zones, the author selected a primary
zone using research and judgment
* Multiple-zone clusters were given a descriptive name
Cluster descriptions were based on either the primary zone description
(the Olson 'region_description' field) -- e.g. "McMurdo Station, Ross
Island" for the cluster containing "Antartica/McMurdo" and
"Antarctica/South_Pole" -- or else a subjectively-determined, broadly
descriptive term common across the zones -- e.g. "Central time" for
various US zones with a UTC-6 offset.
When a country had a single cluster, the cluster description was left
blank, similar to how the Olson database leaves the time zone
description blank. (N.B. the "primary_zones()" function returns the
country name when there is no cluster description.)
Some additional modifications were made to account for errors in the
Olson time zone files.
Cluster names were made on a best-efforts basis by the author. If you
have suggested improvements, please file a bug report with your ideas.
The clustering will be updated over time as the Olson time zone database
changes.
FUNCTIONS
primary_zones
my $zones = primary_zones('US');
Takes a country code and returns a reference to an array of hash
references. Each element in the array represents one timezone cluster in
the country, sorted by UTC offset. The hash reference contains the
following keys:
* description: Description of the zone or the Olson country name if
there is only one cluster
* offset: UTC offset, expressed in hours ('+5', '-2')
* timezone_name: the primary Olson zone name for the cluster
('America/Chicago')
For example, here are some of the items returned from
"primary_zones('AQ')":
[
{
'description' => 'Palmer Station, Anvers Island',
'offset' => -4,
'timezone_name' => 'Antarctica/Palmer'
},
{
'description' => 'Rothera Station, Adelaide Island',
'offset' => -3,
'timezone_name' => 'Antarctica/Rothera'
},
...
]
The description may be the Olson description of the primary zone or it
may be a custom alternative that the author feels best describes the
cluster.
Offsets given are the smallest offset observed during the year. This
should correspond to the non-daylight savings time offset in zones that
observe daylight savings time for part of the year.
The primary zone is the best guess at the most common or recognizable
Olson name in the cluster; see the "DESCRIPTION" section for details.
If an invalid country code is given, the function returns an empty array
reference.
find_primary
my $primary = find_primary("America/Indiana/Indianapolis");
# returns "America/New_York"
Given an Olson time zone name, returns the primary zone name for the
cluster containing the zone. Returns undef or the empty list if the zone
is not recognized.
is_primary {
if ( is_primary("America/Chicago") ) { ... }
A boolean function to check if a time zone is primary for its cluster.
country_codes
for my $cc ( country_codes() ) {
...
}
Returns a sorted list of known country codes in the cluster database.
country_name
my $name = country_name("US");
Returns the Olson country name (or an empty string) for a given country
code. This duplicates information available elsewhere and is provided
here for convenience.
timezone_clusters
for my $cluster ( @{ timezone_clusters('US') } ) {
...
}
Given a country code, returns an array reference of raw cluster data for
the country (or an empty array reference if the country code is not
found).
Each cluster is a hash reference with "description" and "zones". The
"zones" entry is an array reference of time zone hashes similar to that
returned by "primary_zones", but with "olson_description" containing the
the original Olson description rather than "description" for the
cluster. Note that for single-cluster countries, the cluster description
will be blank.
For example, "timezone_clusters("US")" will return a data structure like
this:
[
{
'description' => 'Hawaii',
'zones' => [
{
'offset' => -10,
'olson_description' => 'Hawaii',
'timezone_name' => 'Pacific/Honolulu'
}
]
},
{
'description' => 'Aleutian Islands',
'zones' => [
{
'offset' => -10,
'olson_description' => 'Aleutian Islands',
'timezone_name' => 'America/Adak'
}
]
},
{
'description' => 'Alaska Time',
'zones' => [
{
'offset' => '-9',
'olson_description' => 'Alaska Time',
'timezone_name' => 'America/Anchorage'
},
{
'offset' => -9,
'olson_description' => 'Alaska Time - west Alaska',
'timezone_name' => 'America/Nome'
},
{
'offset' => '-9',
'olson_description' => 'Alaska Time - Alaska panhandle',
'timezone_name' => 'America/Juneau'
},
{
'offset' => '-9',
'olson_description' => 'Alaska Time - Alaska panhandle neck',
'timezone_name' => 'America/Yakutat'
},
{
'offset' => '-9',
'olson_description' => 'Alaska Time - southeast Alaska panhandle',
'timezone_name' => 'America/Sitka'
},
]
},
...
]
find_cluster
my $cluster = find_cluster("America/Indiana/Indianapolis");
Given an Olson time zone name, returns the cluster data structure
containing the time zone. It returns undef or the empty list if the time
zone name is not recognized.
USAGE
All functions are optionally exported using Sub::Exporter.
SEE ALSO
* DateTime::TimeZone::Olson
ACKNOWLEDGMENTS
The author would like to thank the following people for their help:
* Andrew Main (ZEFRAM) for his time zone modules and advice on zone
clustering heuristics.
* Breno Olivera (GARU) for his patient explanations and advice
regarding Brazilian time zones.
Any errors are solely those of the author (or the upstream Olson
database).
SUPPORT
Bugs / Feature Requests
Please report any bugs or feature requests through the issue tracker at
<https://github.com/dagolden/time-olsontz-clustered/issues>. You will be
notified automatically of any progress on your issue.
Source Code
This is open source software. The code repository is available for
public review and contribution under the terms of the license.
<https://github.com/dagolden/time-olsontz-clustered>
git clone git://github.com/dagolden/time-olsontz-clustered.git
AUTHOR
David Golden <dagolden@cpan.org>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2012 by David Golden.
This is free software, licensed under:
The Apache License, Version 2.0, January 2004