File Coverage

blib/lib/Time/OlsonTZ/Clustered.pm
Criterion Covered Total %
statement 68 68 100.0
branch 19 22 86.3
condition 5 7 71.4
subroutine 18 18 100.0
pod 7 7 100.0
total 117 122 95.9


line stmt bran cond sub pod time code
1 6     6   692593 use 5.008001;
  6         25  
  6         296  
2 6     6   31 use strict;
  6         11  
  6         189  
3 6     6   30 use warnings;
  6         9  
  6         507  
4              
5             package Time::OlsonTZ::Clustered;
6             # ABSTRACT: Olson time zone clusters based on similar offset and DST changes
7             our $VERSION = '0.002'; # VERSION
8              
9 6         60 use Sub::Exporter -setup => {
10             exports => [
11             qw/find_cluster find_primary is_primary primary_zones timezone_clusters country_codes country_name/
12             ]
13 6     6   6018 };
  6         75566  
14              
15 6     6   8987 use File::ShareDir::Tarball qw/dist_file/;
  6         806735  
  6         404  
16 6     6   5290 use Path::Class;
  6         184953  
  6         465  
17 6     6   64 use Sereal::Encoder qw/encode_sereal/;
  6         14  
  6         432  
18 6     6   35 use Sereal::Decoder qw/decode_sereal/;
  6         10  
  6         4973  
19              
20             {
21             my $clusters;
22             my $reverse;
23              
24             sub _clusters {
25 15 100   15   92 return $clusters if defined $clusters;
26 5 50       40 my $file = dist_file( 'Time-OlsonTZ-Clustered', 'cluster.srl' )
27             or die "Can't find cluster.srl in distribution share data";
28 5         80219 $clusters = decode_sereal( scalar file($file)->slurp );
29             }
30              
31             sub _get_country {
32 14     14   42 my ($code) = shift;
33 14         78 my $cluster = _clusters()->{ uc $code };
34 14 100       17308 return $cluster ? decode_sereal( encode_sereal($cluster) ) : undef;
35             }
36              
37             sub _reverse_map {
38 8 100   8   68 return $reverse if defined $reverse;
39 3 50       22 my $file = dist_file( 'Time-OlsonTZ-Clustered', 'reverse.srl' )
40             or die "Can't find reverse.srl in distribution share data";
41 3         43296 $reverse = decode_sereal( scalar file($file)->slurp );
42             }
43             }
44              
45             #--------------------------------------------------------------------------#
46             # high level functions
47             #--------------------------------------------------------------------------#
48              
49              
50             sub primary_zones {
51 3     3 1 68 my ($code) = @_;
52              
53 3 100       15 my $country = _get_country($code)
54             or return [];
55 2         9 my $clusters = $country->{clusters};
56 2         14 my $order = $country->{cluster_order};
57 2         8 my $country_name = $country->{olson_name};
58              
59 2         8 my @zones;
60 2         15 for my $c (@$order) {
61 11         28 my $description = $clusters->{$c}{description};
62 11         28 my $first = $clusters->{$c}{zones}[0];
63 11   66     63 my %primary = (
64             description => $description || $country_name,
65             offset => $first->{offset},
66             timezone_name => $first->{timezone_name},
67             );
68 11         34 push @zones, \%primary;
69             }
70 2         56 return \@zones;
71             }
72              
73              
74             sub find_primary {
75 5     5 1 20 my ($zone) = @_;
76 5 100       67 my $cluster = find_cluster($zone)
77             or return;
78 3         24 return $cluster->{zones}[0]{timezone_name};
79             }
80              
81              
82             sub is_primary {
83 3     3 1 11 my ($zone) = @_;
84 3   100     15 my $primary = find_primary($zone) || '';
85 3         26 return $primary eq $zone;
86             }
87              
88             #--------------------------------------------------------------------------#
89             # lower level functions
90             #--------------------------------------------------------------------------#
91              
92              
93             sub country_codes {
94 1     1 1 53 my @list = sort keys %{ _clusters() };
  1         4  
95 1         2926 return @list;
96             }
97              
98              
99             sub country_name {
100 2     2 1 94 my ($code) = @_;
101 2 100       11 my $country = _get_country($code)
102             or return '';
103 1   50     43 return $country->{olson_name} || '';
104             }
105              
106              
107             sub timezone_clusters {
108 4     4 1 3389 my ($code) = @_;
109 4 100       18 my $country = _get_country($code)
110             or return [];
111 3         11 my $clusters = $country->{clusters};
112 3         6 my $order = $country->{cluster_order};
113              
114 3         13 return [ map { $clusters->{$_} } @$order ];
  19         75  
115             }
116              
117              
118             sub find_cluster {
119 8     8 1 93 my ($zone) = @_;
120 8 100       25 my $reverse = _reverse_map()->{$zone}
121             or return;
122 5         3243 my ( $code, $digest ) = @$reverse;
123 5 50       22 my $country = _get_country($code)
124             or return;
125 5         88 return $country->{clusters}{$digest};
126             }
127              
128             1;
129              
130              
131             # vim: ts=4 sts=4 sw=4 et:
132              
133             __END__