File Coverage

blib/lib/Time/Piece/Adaptive.pm
Criterion Covered Total %
statement 43 106 40.5
branch 2 44 4.5
condition 0 18 0.0
subroutine 13 24 54.1
pod 5 5 100.0
total 63 197 31.9


line stmt bran cond sub pod time code
1             package Time::Piece::Adaptive;
2              
3 1     1   31790 use warnings;
  1         3  
  1         33  
4 1     1   7 use strict;
  1         3  
  1         37  
5              
6 1     1   6 no warnings 'redefine';
  1         6  
  1         60  
7              
8             =head1 VERSION
9              
10             Version 0.03
11              
12             =cut
13              
14             our $VERSION = 0.03;
15              
16             =head1 NAME
17              
18             Time::Piece::Adaptive - subclass of Time::Piece which allows the default
19             stringification function to be set.
20              
21             =head1 REQUIRES
22              
23             Subclasses Time::Piece.
24              
25             =head1 SYNOPSIS
26              
27             See Time::Piece
28              
29             I actually think this subclass encapsulates the behavior I would expect from
30             Time::Piece, but I haven't been able to elicit a response from the authors of
31             Time::Piece.
32              
33             =head1 EXPORT
34              
35             =over 4
36              
37             =item * gmtime
38              
39             =item * localtime
40              
41             =item * :override:
42              
43             =back
44              
45             See Time::Piece for more.
46              
47             =cut
48              
49 1     1   6 use vars qw(@ISA @EXPORT %EXPORT_TAGS);
  1         2  
  1         87  
50              
51             require Exporter;
52             require DynaLoader;
53 1     1   1067 use Time::Piece;
  1         16550  
  1         6  
54              
55             @ISA = qw(Time::Piece);
56              
57             @EXPORT = qw(
58             localtime
59             gmtime
60             );
61              
62             %EXPORT_TAGS = (
63             ':override' => 'internal',
64             );
65              
66             my %_special_exports = (
67 0     0   0 localtime => sub { my $c = $_[0]; sub { $c->localtime(@_) } },
68 0     0   0 gmtime => sub { my $c = $_[0]; sub { $c->gmtime(@_) } },
69             );
70              
71             sub _export
72             {
73 1     1   3 my ($class, $to, @methods) = @_;
74 1         3 for my $method (@methods)
75             {
76 2 50       6 if (exists $_special_exports{$method})
77             {
78 1     1   262 no strict 'refs';
  1         2  
  1         74  
79 1     1   7 no warnings 'redefine';
  1         2  
  1         655  
80 2         5 *{$to . "::$method"} = $_special_exports{$method}->($class);
  2         23  
81             } else {
82 0         0 $class->SUPER::export ($to, $method);
83             }
84             }
85             }
86              
87             sub import
88             {
89             # replace CORE::GLOBAL localtime and gmtime if required
90 1     1   10 my $class = shift;
91 1         2 my %params;
92 1         4 map $params{$_}++, @_, @EXPORT;
93 1 50       5 if (delete $params{':override'})
94             {
95 0         0 $class->_export ('CORE::GLOBAL', keys %params);
96             }
97             else
98             {
99 1         6 $class->_export((caller)[0], keys %params);
100             }
101             }
102              
103              
104              
105             =head1 METHODS
106              
107             =head2 new
108              
109             my $t1 = new Time::Piece::Adaptive (time, stringify => "%Y%m%d%H%M%S");
110             print "The MySql timestamp was $t1.";
111              
112             my $t2 = new Time::Piece::Adaptive (time,
113             stringify => \&my_func,
114             stringify_args => $my_data);
115              
116             Like the constructor for Time::Piece, except it may set the default
117             stringify function.
118              
119             The above examples are semanticly equivalent to:
120              
121             my $t1 = new Time::Piece::Adaptive (time);
122             $t1->set_stringify ("%Y%m%d%H%M%S");
123             print "The MySql timestamp was $t1.";
124              
125             my $t2 = new Time::Piece::Adaptive (time);
126             $t2->set_stringify (\&my_func, $my_data);
127              
128             =cut
129              
130             sub new
131             {
132 0     0 1   my $class = shift;
133 0 0 0       my $time = shift
      0        
134             unless $_[0] && ($_[0] eq "stringify" || $_[0] eq "stringify_arg");
135 0           my %args = @_;
136              
137 0           my $self = $class->SUPER::new ($time);
138 0 0         my $stringify = $args{stringify} if exists $args{stringify};
139 0 0         my $stringify_args = $args{stringify_args} if exists $args{stringify_args};
140 0           $self->set_stringify ($stringify, $stringify_args);
141 0           return $self;
142             }
143              
144              
145              
146             =head2 localtime
147              
148             =head2 gmtime
149              
150             C and C work like Time::Piece's versions, except they accept
151             stringify arguments, as C.
152              
153             =cut
154              
155             sub localtime {
156 0 0   0     unshift @_, __PACKAGE__ unless eval {$_[0]->isa ('Time::Piece')};
  0            
157 0           my $class = shift;
158 0 0 0       my $time = shift
      0        
159             unless $_[0] && ($_[0] eq "stringify" || $_[0] eq "stringify_arg");
160 0 0         $time = time unless defined $time;
161 0           return $class->_mktime ($time, 1, @_);
162             }
163              
164             sub gmtime {
165 0 0   0     unshift @_, __PACKAGE__ unless eval {$_[0]->isa ('Time::Piece')};
  0            
166 0           my $class = shift;
167 0 0 0       my $time = shift
      0        
168             unless $_[0] && ($_[0] eq "stringify" || $_[0] eq "stringify_arg");
169 0 0         $time = time unless defined $time;
170 0           return $class->_mktime ($time, 0, @_);
171             }
172              
173             sub _mktime
174             {
175 0     0     my ($class, $time, $islocal, %args) = @_;
176 0 0         return $class->SUPER::_mktime ($time) if wantarray;
177              
178 0           my $self = $class->SUPER::_mktime ($time);
179 0 0         my $stringify = $args{stringify} if exists $args{stringify};
180 0 0         my $stringify_args = $args{stringify_args} if exists $args{stringify_args};
181 0           $self->set_stringify ($stringify, $stringify_args);
182 0           return $self;
183             }
184              
185             =head2 set_stringify
186              
187             $t->set_stringify ($format, $arg);
188             print "The date is $t.";
189              
190             If C<$format> is a reference to a function, set the stringify function to
191             C<$format>, which should return a string when passed a reference to an
192             instantiated Time::Piece and C<$arg>.
193              
194             If C<$format> is a string, use it to format an output string using
195             C (any C<$arg> is ignored).
196              
197             When called without specifying C<$format>, restore the default stringifier
198             (C<&Time::Piece::cdate>).
199              
200             =cut
201              
202 1     1   5 use overload '""' => \&_stringify;
  1         2  
  1         5  
203              
204 1     1   59 use constant 'c_stringify_func' => 11;
  1         1  
  1         63  
205 1     1   5 use constant 'c_stringify_arg' => 12;
  1         2  
  1         1977  
206              
207             sub _stringify
208             {
209 0     0     my ($self) = @_;
210 0           my $func = $self->[c_stringify_func];
211 0           my $arg = $self->[c_stringify_arg];
212 0           my $string = &{$func}($self, $arg);
  0            
213 0           return $string;
214             }
215              
216              
217              
218             sub set_stringify
219             {
220 0     0 1   my ($self, $format, $arg) = @_;
221 0 0         if (ref $format) {
    0          
222 0           $self->[c_stringify_func] = $format;
223 0 0         if (defined $arg) {
224 0 0         $self->[c_stringify_arg] = $arg if defined $arg;
225             } else {
226 0           delete $self->[c_stringify_arg];
227             }
228             } elsif (defined $format) {
229 0           $self->[c_stringify_func] = \&Time::Piece::strftime;
230 0           $self->[c_stringify_arg] = $format;
231             } else {
232 0           $self->[c_stringify_func] = \&Time::Piece::cdate;
233 0           delete $self->[c_stringify_arg];
234             }
235             }
236              
237              
238              
239             =head2 add
240              
241             =head2 subtract
242              
243             Like the Time::Piece functions of the same name, except C and
244             C arguments are accepted.
245              
246             Also, when a Time::Piece::Adaptive object is subtracted from an arbitrary
247             object, it is converted to a string according to its stringify function and
248             passed to perl for handling.
249              
250             =cut
251              
252             use overload
253 1         7 '-' => \&subtract,
254 1     1   9 '+' => \&add;
  1         2  
255              
256             sub subtract
257             {
258 0     0 1   my $time = shift;
259              
260 0 0         if ($_[1])
261             {
262             # SWAPED is set and our parent doesn't know how to handle
263             # NOTDATE - DATE. For backwards compatibility reasons, return
264             # the result as if the string $time resolves to was subtracted
265             # from NOTDATE.
266 0           return $_[0] - "$time";
267             }
268              
269 0           my $new = $time->SUPER::subtract (@_);
270 0 0         $new->set_stringify ($time->[c_stringify_func],
271             $time->[c_stringify_arg])
272             if $new->isa ('Time::Piece');
273 0           return $new;
274             }
275              
276             sub add
277             {
278 0     0 1   my ($time) = shift;
279 0           my $new = $time->SUPER::add (@_);
280 0           $new->set_stringify ($time->[c_stringify_func],
281             $time->[c_stringify_arg]);
282 0           return $new;
283             }
284              
285              
286              
287             =head2 strptime
288              
289             my $t = Time::Piece::Adaptive::strptime ($mysqltime, "%Y%m%d%H%M%S");
290             print "The MySql timestamp was $t.";
291              
292             my $t = Time::Piece::Adaptive::strptime ($mysqltime, "%Y%m%d%H%M%S",
293             stringify =>
294             \&Time::Piece::Adaptive::cdate);
295             print "The MySql timestamp was $t.";
296              
297              
298             Like the C, except a stringify function may be set as
299             per C and, if the stringify function is not
300             explicitly specified, then it is set by calling C on
301             the new object with the same C<$format> string passed to C.
302              
303             =cut
304              
305             sub strptime
306             {
307 0     0 1   my ($time, $string, $format, %args) = @_;
308 0           my $self = $time->SUPER::strptime ($string, $format);
309 0 0         my $stringify = exists $args{stringify} ? $args{stringify} : $format;
310 0 0         my $stringify_args = $args{stringify_args} if exists $args{stringify_args};
311 0           $self->set_stringify ($stringify, $stringify_args);
312 0           return $self;
313             }
314              
315             =head1 SEE ALSO
316              
317             =over 4
318              
319             =item L
320              
321             =back
322              
323             =head1 AUTHOR
324              
325             Derek Price, C<< >>
326              
327             =head1 BUGS
328              
329             Please report any bugs or feature requests to
330             C, or through the web interface at
331             L.
332             I will be notified, and then you'll automatically be notified of progress on
333             your bug as I make changes.
334              
335             =head1 SUPPORT
336              
337             You can find documentation for this module with the perldoc command.
338              
339             perldoc Time::Piece::Adaptive
340              
341             You can also look for information at:
342              
343             =over 4
344              
345             =item * AnnoCPAN: Annotated CPAN documentation
346              
347             L
348              
349             =item * CPAN Ratings
350              
351             L
352              
353             =item * RT: CPAN's request tracker
354              
355             L
356              
357             =item * Search CPAN
358              
359             L
360              
361             =back
362              
363             =head1 COPYRIGHT & LICENSE
364              
365             Copyright 2006 Derek Price, all rights reserved.
366              
367             This program is free software; you can redistribute it and/or modify it
368             under the same terms as Perl itself.
369              
370             =cut
371              
372             1;