File Coverage

blib/lib/perl5i/2/DateTime.pm
Criterion Covered Total %
statement 85 93 91.4
branch 24 34 70.5
condition 1 3 33.3
subroutine 23 24 95.8
pod 0 3 0.0
total 133 157 84.7


line stmt bran cond sub pod time code
1             package perl5i::2::DateTime;
2              
3             # A file to contain the Datetime work for perl5i to get it out of perl5i.pm
4              
5 103     103   3059 use 5.010;
  103         399  
  103         6550  
6 103     103   1626 use strict;
  103         238  
  103         5639  
7 103     103   777 use warnings;
  103         415  
  103         13005  
8              
9             # Determine if we need Time::y2038 and only load if necessary.
10             # XXX This is a bit of a hack and should go into a config file.
11 103   33     21784 use constant NEEDS_y2038 => (
12             ((((CORE::gmtime(2**47-1))[5] || 0) + 1900) != 4461763) ||
13             ((((CORE::gmtime(-62135510400))[5] || 0) + 1900) != 1)
14 103     103   745 );
  103         355  
15              
16             BEGIN {
17 103     103   135335 if( NEEDS_y2038 ) {
18             require Time::y2038;
19             Time::y2038->import;
20             }
21             }
22              
23             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
24             sub dt_gmtime (;$) {
25 13 100   13 0 10851 my $time = @_ ? shift : time;
26 13 100       68 return gmtime($time) if wantarray;
27              
28 10         48 my($sec, $min, $hour, $mday, $mon, $year) = gmtime($time);
29 10         25 $mon++;
30 10         19 $year += 1900;
31              
32 10         1770 require DateTime;
33 10         145496 return perl5i::2::DateTime::y2038->new(
34             year => $year,
35             month => $mon,
36             day => $mday,
37             hour => $hour,
38             minute => $min,
39             second => $sec,
40             formatter => "perl5i::2::DateTime::Format::CTime"
41             );
42             }
43              
44              
45             sub _get_datetime_timezone {
46 2     2   8 state $local_tzfile = "/etc/localtime";
47              
48             # Always be sure to honor the TZ environment var
49 2 50       12 return "local" if $ENV{TZ};
50              
51             # Work around a bug in DateTime::TimeZone on FreeBSD where it
52             # can't determine the time zone if /etc/localtime is not a link.
53             # Tzfile is also faster to do localtime calculations.
54 2 50       46 if( -e $local_tzfile ) {
55             # Could go through more effort to figure it out. Meh.
56 2         4 my $tzname = "Local";
57 2 50       37 if( -l $local_tzfile ) {
58 0 0       0 if( my $real_tzfile = eval { readlink $local_tzfile } ) {
  0         0  
59 0         0 $tzname = $real_tzfile;
60             }
61             }
62 2         2346 require DateTime::TimeZone::Tzfile;
63 2         3353506 my $tz = DateTime::TimeZone::Tzfile->new(
64             name => $tzname,
65             filename => $local_tzfile
66             );
67 2 50       6031941 return $tz if $tz;
68             }
69              
70 0         0 return "local";
71             }
72              
73             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
74             sub dt_localtime (;$) {
75 9 100   9 0 6805 my $time = @_ ? shift : time;
76 9 100       104 return localtime($time) if wantarray;
77              
78 4         483 my($sec, $min, $hour, $mday, $mon, $year) = localtime($time);
79 4         11 $mon++;
80 4         11 $year += 1900;
81              
82 4         16 state $tz = _get_datetime_timezone();
83              
84 4         3612 require DateTime;
85 4         1432865 return perl5i::2::DateTime::y2038->new(
86             year => $year,
87             month => $mon,
88             day => $mday,
89             hour => $hour,
90             minute => $min,
91             second => $sec,
92             time_zone => $tz,
93             formatter => "perl5i::2::DateTime::Format::CTime"
94             );
95             }
96              
97              
98             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
99             sub dt_time () {
100 24     24 0 22328514 require DateTime::Format::Epoch;
101 24         299379 state $formatter = DateTime::Format::Epoch->new( epoch => DateTime->from_epoch( epoch => 0 ) );
102              
103 24         2653 require DateTime;
104 24         230 return perl5i::2::DateTime::time->from_epoch(
105             epoch => time,
106             formatter => $formatter
107             );
108             }
109              
110              
111             {
112             package perl5i::2::DateTime::y2038;
113              
114             # Don't load DateTime until we need it.
115             our @ISA = qw(DateTime);
116              
117             use overload
118             "eq" => sub {
119 5     5   4472 my($dt1, $dt2) = @_;
120 5 50       15 return "$dt1" eq "$dt2" if !eval { $dt2->isa("DateTime") };
  5         69  
121 0         0 return $dt1 eq $dt2;
122 103     103   952 };
  103         271  
  103         1986  
123              
124             sub say {
125 2     2   717 CORE::say("$_[0]");
126             }
127              
128             sub print {
129 2     2   505 CORE::print("$_[0]");
130             }
131              
132             sub from_epoch {
133 24     24   66 my $class = shift;
134              
135 24         35 if( perl5i::2::DateTime::NEEDS_y2038 ) {
136 103     103   25009 no warnings 'redefine';
  103         387  
  103         39479  
137             local *CORE::GLOBAL::gmtime = \&Time::y2038::gmtime;
138             local *CORE::GLOBAL::localtime = \&Time::y2038::localtime;
139              
140             return $class->SUPER::from_epoch(@_);
141             }
142             else {
143 24         152 return $class->SUPER::from_epoch(@_);
144             }
145             }
146              
147              
148             # Copy of DateTime's own epoch() function.
149             if( perl5i::2::DateTime::NEEDS_y2038 ) {
150             *epoch = sub {
151             my $self = shift;
152              
153             my $zone = $self->time_zone;
154             $self->set_time_zone("UTC");
155              
156             require Time::y2038;
157             my $time = Time::y2038::timegm(
158             $self->sec, $self->min, $self->hour, $self->mday,
159             $self->mon - 1,
160             $self->year - 1900,
161             );
162              
163             $self->set_time_zone($zone);
164              
165             return $time;
166             }
167             }
168             }
169              
170             {
171              
172             package perl5i::2::DateTime::time;
173              
174 103     103   829 use parent -norequire, qw(perl5i::2::DateTime::y2038);
  103         265  
  103         1313  
175              
176             use overload
177 9     9   1301 "0+" => sub { $_[0]->epoch },
178             "-" => sub {
179 8     8   2379 my( $a, $b, $reverse ) = @_;
180              
181 8 100       51 if($reverse) {
182 2         5 ( $b, $a ) = ( $a, $b );
183             }
184              
185 8 100       47 my $time_a = eval { $a->isa("DateTime") } ? $a->epoch : $a;
  8         130  
186 8 100       84 my $time_b = eval { $b->isa("DateTime") } ? $b->epoch : $b;
  8         90  
187              
188 8         84 return $time_a - $time_b;
189             },
190              
191             "+" => sub {
192 3     3   488 my( $a, $b, $reverse ) = @_;
193              
194 3 50       12 if($reverse) {
195 0         0 ( $b, $a ) = ( $a, $b );
196             }
197              
198 3 50       8 my $time_a = eval { $a->isa("DateTime") } ? $a->epoch : $a;
  3         40  
199 3 100       26 my $time_b = eval { $b->isa("DateTime") } ? $b->epoch : $b;
  3         25  
200              
201 3         22 return $time_a + $time_b;
202             },
203              
204             "==" => sub {
205 1     1   6 my($a, $b) = @_;
206 1 50       2 return $a+0 == $b+0 if !eval { $b->isa("DateTime") };
  1         14  
207 0         0 return $a == $b;
208             },
209              
210 103     103   90198 fallback => 1;
  103         262  
  103         2561  
211             }
212              
213              
214             {
215              
216             package perl5i::2::DateTime::Format::CTime;
217              
218 103     103   65680 use CLASS;
  103         17621  
  103         819  
219              
220             sub new {
221 0     0   0 return bless {}, $CLASS;
222             }
223              
224             sub format_datetime {
225 13     13   4425 my $self = shift;
226 13         21 my $dt = shift;
227              
228             # Straight from the Open Group asctime() docs.
229 13         59 return sprintf "%.3s %.3s%3d %.2d:%.2d:%.2d %d",
230             $dt->day_abbr,
231             $dt->month_abbr,
232             $dt->mday,
233             $dt->hour,
234             $dt->min,
235             $dt->sec,
236             $dt->year,
237             ;
238             }
239             }
240              
241              
242             1;