File Coverage

blib/lib/DateTime/TimeZone/Local.pm
Criterion Covered Total %
statement 48 49 97.9
branch 12 14 85.7
condition 1 3 33.3
subroutine 13 13 100.0
pod 2 2 100.0
total 76 81 93.8


line stmt bran cond sub pod time code
1             package DateTime::TimeZone::Local;
2              
3 20     20   169 use strict;
  20         42  
  20         807  
4 20     20   100 use warnings;
  20         35  
  20         1136  
5 20     20   111 use namespace::autoclean;
  20         36  
  20         158  
6              
7             our $VERSION = '2.67';
8              
9 20     20   2667 use DateTime::TimeZone;
  20         36  
  20         570  
10 20     20   101 use File::Spec;
  20         38  
  20         761  
11 20     20   95 use Module::Runtime qw( require_module );
  20         53  
  20         202  
12 20     20   1052 use Try::Tiny;
  20         38  
  20         14911  
13              
14             sub TimeZone {
15 285     285 1 1471199 my $class = shift;
16              
17 285         1081 my $subclass = $class->_load_subclass();
18              
19 285         1944 for my $meth ( $subclass->Methods() ) {
20 293         1025 my $tz = $subclass->$meth();
21              
22 293 100       1465 return $tz if $tz;
23             }
24              
25 0         0 die "Cannot determine local time zone\n";
26             }
27              
28             {
29             # Stolen from File::Spec. My theory is that other folks can write
30             # the non-existent modules if they feel a need, and release them
31             # to CPAN separately.
32             my %subclass = (
33             android => 'Android',
34             cygwin => 'Unix',
35             dos => 'OS2',
36             epoc => 'Epoc',
37             MacOS => 'Mac',
38             MSWin32 => 'Win32',
39             NetWare => 'Win32',
40             os2 => 'OS2',
41             symbian => 'Win32',
42             VMS => 'VMS',
43             );
44              
45             sub _load_subclass {
46 287     287   1008885 my $class = shift;
47              
48 287   33     2365 my $os_name = $subclass{$^O} || $^O;
49 287         703 my $subclass = $class . '::' . $os_name;
50              
51 287 100       2859 return $subclass if $subclass->can('Methods');
52              
53             return $subclass if try {
54             ## no critic (Variables::RequireInitializationForLocalVars)
55 286     286   7775 local $SIG{__DIE__};
56 286         1029 require_module($subclass);
57 286 50       1575 };
58              
59 286         50125 $subclass = $class . '::Unix';
60              
61 286         1183 require_module($subclass);
62              
63 286         8479 return $subclass;
64             }
65             }
66              
67             sub FromEnv {
68 288     288 1 3995 my $class = shift;
69              
70 288         754 foreach my $var ( $class->EnvVars() ) {
71 288 100       1218 if ( $class->_IsValidName( $ENV{$var} ) ) {
72             my $tz = try {
73             ## no critic (Variables::RequireInitializationForLocalVars)
74 284     284   7503 local $SIG{__DIE__};
75 284         1516 DateTime::TimeZone->new( name => $ENV{$var} );
76 284         1561 };
77              
78 284 100       5227 return $tz if $tz;
79             }
80             }
81              
82 6         20 return;
83             }
84              
85             sub _IsValidName {
86 293     293   414 shift;
87              
88 293 100       863 return 0 unless defined $_[0];
89 292 50       675 return 0 if $_[0] eq 'local';
90              
91 292         1582 return $_[0] =~ m{^[\w/\-\+]+$};
92             }
93              
94             1;
95              
96             # ABSTRACT: Determine the local system's time zone
97              
98             __END__
99              
100             =pod
101              
102             =encoding UTF-8
103              
104             =head1 NAME
105              
106             DateTime::TimeZone::Local - Determine the local system's time zone
107              
108             =head1 VERSION
109              
110             version 2.67
111              
112             =head1 SYNOPSIS
113              
114             my $tz = DateTime::TimeZone->new( name => 'local' );
115              
116             my $tz = DateTime::TimeZone::Local->TimeZone();
117              
118             =head1 DESCRIPTION
119              
120             This module provides an interface for determining the local system's time zone.
121             Most of the functionality for doing this is in OS-specific subclasses.
122              
123             =head1 USAGE
124              
125             This class provides the following methods:
126              
127             =head2 DateTime::TimeZone::Local->TimeZone()
128              
129             This attempts to load an appropriate subclass and asks it to find the local
130             time zone. This method is called by when you pass "local" as the time zone name
131             to C<< DateTime:TimeZone->new() >>.
132              
133             If your OS is not explicitly handled, you can create a module with a name of
134             the form C<DateTime::TimeZone::Local::$^O>. If it exists, it will be used
135             instead of falling back to the Unix subclass.
136              
137             If no OS-specific module exists, we fall back to using the Unix subclass.
138              
139             See L<DateTime::TimeZone::Local::Unix>, L<DateTime::TimeZone::Local::Android>,
140             L<DateTime::TimeZone::Local::hpux>, L<DateTime::TimeZone::Local::Win32>, and
141             L<DateTime::TimeZone::Local::VMS> for OS-specific details.
142              
143             =head1 SUBCLASSING
144              
145             If you want to make a new OS-specific subclass, there are several methods
146             provided by this module you should know about.
147              
148             =head2 $class->Methods()
149              
150             This method should be provided by your class. It should provide a list of
151             methods that will be called to try to determine the local time zone.
152              
153             Each of these methods is expected to return a new C<DateTime::TimeZone> object
154             if it can successfully determine the time zone.
155              
156             =head2 $class->FromEnv()
157              
158             This method tries to find a valid time zone in an C<%ENV> value. It calls C<<
159             $class->EnvVars() >> to determine which keys to look at.
160              
161             To use this from a subclass, simply return "FromEnv" as one of the items from
162             C<< $class->Methods() >>.
163              
164             =head2 $class->EnvVars()
165              
166             This method should be provided by your subclass. It should return a list of env
167             vars to be checked by C<< $class->FromEnv() >>.
168              
169             Your class should always include the C<TZ> key as one of the variables to
170             check.
171              
172             =head2 $class->_IsValidName($name)
173              
174             Given a possible time zone name, this returns a boolean indicating whether or
175             not the name looks valid. It always return false for "local" in order to avoid
176             infinite loops.
177              
178             =head1 EXAMPLE SUBCLASS
179              
180             Here is a simple example subclass:
181              
182             package DateTime::TimeZone::SomeOS;
183              
184             use strict;
185             use warnings;
186              
187             use base 'DateTime::TimeZone::Local';
188              
189              
190             sub Methods { qw( FromEnv FromEther ) }
191              
192             sub EnvVars { qw( TZ ZONE ) }
193              
194             sub FromEther
195             {
196             my $class = shift;
197              
198             ...
199             }
200              
201             =head1 SUPPORT
202              
203             Bugs may be submitted at L<https://github.com/houseabsolute/DateTime-TimeZone/issues>.
204              
205             =head1 SOURCE
206              
207             The source code repository for DateTime-TimeZone can be found at L<https://github.com/houseabsolute/DateTime-TimeZone>.
208              
209             =head1 AUTHOR
210              
211             Dave Rolsky <autarch@urth.org>
212              
213             =head1 COPYRIGHT AND LICENSE
214              
215             This software is copyright (c) 2026 by Dave Rolsky.
216              
217             This is free software; you can redistribute it and/or modify it under
218             the same terms as the Perl 5 programming language system itself.
219              
220             The full text of the license can be found in the
221             F<LICENSE> file included with this distribution.
222              
223             =cut