File Coverage

blib/lib/DateTime/Format/GeekTime.pm
Criterion Covered Total %
statement 36 42 85.7
branch 4 8 50.0
condition 3 6 50.0
subroutine 8 9 88.8
pod 3 3 100.0
total 54 68 79.4


line stmt bran cond sub pod time code
1             package DateTime::Format::GeekTime;
2 3     3   1700176 use 5.005;
  3         18  
3 3     3   21 use strict;
  3         9  
  3         81  
4 3     3   18 use warnings;
  3         11  
  3         158  
5 3     3   24 use DateTime;
  3         10  
  3         72  
6 3     3   21 use Carp;
  3         8  
  3         277  
7 3     3   28 use vars '$VERSION';
  3         8  
  3         1374  
8              
9             $VERSION='1.000_002';
10             $VERSION=eval $VERSION;
11              
12             sub new {
13 0     0 1 0 my ($class,$year)=@_;
14              
15 0 0       0 if (!defined $year) {
16 0         0 $year = DateTime->now->year;
17             }
18              
19 0         0 return bless {year=>$year},$class;
20             }
21              
22             sub parse_datetime {
23 11     11 1 10639 my ($self,$string)=@_;
24              
25 11         99 my ($seconds,$days) =
26             ($string =~ m{\A \s*
27             (?:0x)? ( [0-9a-fA-F]{4} )
28             (?: [\w\s]*? )
29             (?:0x)? ( [0-9a-fA-F]{3,4} )
30             (?: \s+ .)? # optional character representation
31             \s* \z}smx);
32 11 50 33     83 if (!(defined $seconds and defined $days)) {
33 0         0 croak "<$string> is not a proper GeekTime string";
34             }
35              
36 11         33 $seconds=hex($seconds);$days=hex($days);
  11         26  
37              
38 11         40 $seconds=int($seconds*86_400/65_536+0.5);
39              
40 11         26 my $base_year;
41 11 50       33 if (ref($self)) {
42 0         0 $base_year=$self->{year};
43             }
44             else {
45 11         49 $base_year=DateTime->now->year;
46             }
47              
48 11         3416 my $dt=DateTime->new(year=>$base_year,time_zone=>'UTC');
49 11         3799 $dt->add(days=>$days,seconds=>$seconds);
50              
51 11         9853 return $dt;
52             }
53              
54             sub format_datetime {
55 2     2 1 13199 my ($self,$dt)=@_;
56              
57 2         12 my $start_of_day=$dt->clone->set_time_zone('UTC')->truncate(to=>'day');
58              
59 2         960 my $seconds=$dt->subtract_datetime_absolute($start_of_day)->in_units('seconds');
60              
61 2         405 my $days=$dt->day_of_year - 1;
62              
63 2         20 $seconds=int($seconds/86_400*65_536+0.5);
64              
65 2 100 66     24 my $chr = $seconds <= 0xD800 || $seconds >= 0xDFFF
66             ? ' '.chr($seconds)
67             : '';
68              
69 2         33 return sprintf '0x%04X on day 0x%03X%s',$seconds,$days,$chr;
70             }
71              
72             1;
73             __END__
74              
75             =head1 NAME
76              
77             DateTime::Format::GeekTime - parse and format GeekTime
78              
79             =head1 SYNOPSIS
80              
81             use DateTime::Format::GeekTime;
82             use DateTime;
83              
84             my $dt=DateTime->now();
85             print DateTime::Format::GeekTime->format_datetime($dt);
86              
87             $dt=DateTime::Format::GeekTime->parse_datetime('0xBA45 on day 0x042');
88              
89             $dt=DateTime::Format::GeekTime->new(2010)
90             ->parse_datetime('0xBA45 on day 0x042');
91              
92             =head1 DESCRIPTION
93              
94             This module formats and parses "GeekTime". See L<http://geektime.org/>
95             for the inspiration.
96              
97             =head1 METHODS
98              
99             =over 4
100              
101             =item C<new>
102              
103             my $dtf=DateTime::Format::GeekTime->new(2010);
104              
105             The single optional parameter to C<new> is the year to use for
106             parsing. Since GeekTime does not carry this information, we have to
107             supply it externally. If you don't specify it, or if you call
108             C<parse_datetime> as a class method, the current yuor will be used.
109              
110             =item C<format_datetime>
111              
112             my $string=DateTime::Format::GeekTime->format_datetime($dt);
113              
114             Returns the full GeekTime string, like C<0x0041 on day 0x042 A>.
115              
116             Note the character at the end of the string: it's the character
117             corresponding to the Unicode codepoint with the same value as the
118             first word in the string. If the codepoint corresponds to a "high
119             surrogate" or a "low surrogate", the character (and the preceding
120             space) will not be returned.
121              
122             =item C<parse_datetime>
123              
124             my $dt=DateTime::Format::GeekTime->parse_datetime('0xb4b1 0x0042');
125              
126             Parses a GeekTime and returns a C<DateTime> object.
127              
128             The parsing is somewhat lenient: you can omit the C<0x>, you can
129             express the day as 3 or 4 digits, all space is optional (as is the "on
130             day" in the middle). The character after the day number is ignored, if
131             present.
132              
133             =back
134              
135             =head1 NOTES
136              
137             Since GeekTime divides the day in 65536 intervals, but we usually
138             divide it in 86400 seconds, don't expect all times to round-trip
139             correctly: some loss of precision is to be expected. Note that going
140             from GeekTime to a C<DateTime> object and back to GeekTime is
141             guaranteed to give you the same numbers you started from. Going the
142             other way can lose one second.
143              
144             =head1 AUTHOR
145              
146             Gianni Ceccarelli <dakkar@thenautilus.net>
147              
148             GeekTime http://geektime.org/ http://twitter.com/geektime
149              
150             =head1 COPYRIGHT and LICENSE
151              
152             This program is E<copy> 2010 Gianni Ceccarelli. This library is free
153             software; you can redistribute it and/or modify it under the same
154             terms as Perl itself.
155              
156             =head1 SEE ALSO
157              
158             http://geektime.org/
159              
160             L<DateTime>
161              
162             =cut