File Coverage

blib/lib/Date/TimeOfDay.pm
Criterion Covered Total %
statement 117 121 96.6
branch 41 58 70.6
condition 11 20 55.0
subroutine 27 28 96.4
pod 16 16 100.0
total 212 243 87.2


line stmt bran cond sub pod time code
1             package Date::TimeOfDay;
2              
3             our $DATE = '2018-12-17'; # DATE
4             our $VERSION = '0.004'; # VERSION
5              
6 1     1   70518 use 5.010001;
  1         4  
7 1     1   6 use strict;
  1         2  
  1         23  
8 1     1   4 use warnings;
  1         3  
  1         44  
9 1     1   510 use POSIX 'round';
  1         6799  
  1         7  
10              
11             use overload (
12             #fallback => 1,
13             '<=>' => '_compare_overload',
14             'cmp' => '_string_compare_overload',
15             q{""} => 'stringify',
16             q{0+} => 'float',
17 2     2   9 bool => sub {1},
18             #'-' => '_subtract_overload',
19             #'+' => '_add_overload',
20 1         9 'eq' => '_string_equals_overload',
21             'ne' => '_string_not_equals_overload',
22 1     1   2791 );
  1         1006  
23              
24             sub new {
25 8     8 1 4015 my $class = shift;
26 8         35 my %args = @_;
27              
28 8         15 my $tod = 0;
29 8 100       23 if (defined $args{hour}) {
30             die "'hour' must be an integer"
31 7 50       25 unless $args{hour} == int($args{hour});
32             die "'hour' must be between 0 & 23"
33 7 100 66     50 unless $args{hour} >= 0 && $args{hour} <= 23;
34 6         13 $tod += delete($args{hour}) * 3600;
35             } else {
36 1         12 die "Please specify 'hour'";
37             }
38 6 50       19 if (defined $args{minute}) {
39             die "'minute' must be an integer"
40 6 50       17 unless $args{minute} == int($args{minute});
41             die "'minute' must be between 0 & 59"
42 6 50 33     25 unless $args{minute} >= 0 && $args{minute} <= 59;
43 6         12 $tod += delete($args{minute}) * 60;
44             } else {
45 0         0 die "Please specify 'minute'";
46             }
47 6 50       13 if (defined $args{second}) {
48             die "'second' must be an integer"
49 6 50       16 unless $args{second} == int($args{second});
50             die "'second' must be between 0 & 59"
51 6 50 33     22 unless $args{second} >= 0 && $args{second} <= 59;
52 6         11 $tod += delete($args{second});
53             } else {
54 0         0 die "Please specify 'second'";
55             }
56              
57 6 50       13 if (defined $args{nanosecond}) {
58             die "'nanosecond' must be an integer"
59 6 50       17 unless $args{nanosecond} == int($args{nanosecond});
60             die "'nanosecond' must be between 0 & 999_999_999"
61 6 50 33     21 unless $args{nanosecond} >= 0 && $args{nanosecond} <= 999_999_999;
62 6         16 $tod += delete($args{nanosecond}) / 1e9;
63             }
64              
65 6 100       29 die "Unknown parameter(s): ".join(", ", sort keys %args) if keys %args;
66              
67 5         21 return bless \$tod, $class;
68             }
69              
70             sub from_float {
71 10     10 1 11265 my $class = shift;
72 10         29 my %args = @_;
73              
74 10         14 my $tod;
75 10 100       22 if (defined $args{float}) {
76 9         19 $tod = delete($args{float}) + 0;
77 9 100 100     55 die "'float' must be between 0-86400"
78             unless $tod >= 0 && $tod < 86400;
79             } else {
80 1         10 die "Please specify 'float'";
81             }
82              
83 7 100       28 die "Unknown parameter(s): ".join(", ", sort keys %args) if keys %args;
84              
85 6         20 return bless \$tod, $class;
86             }
87              
88             sub from_hms {
89 4     4 1 3751 my $class = shift;
90 4         15 my %args = @_;
91              
92 4         6 my $tod;
93 4 50       12 if (defined $args{hms}) {
94 4         8 my $hms = delete $args{hms};
95 4 50       34 $hms =~ /\A([0-9]{1,2}):([0-9]{1,2})(?::([0-9]{1,2})(\.[0-9]{1,9})?)?\z/
96             or die "Invalid hms '$hms', must be hh:mm:ss or hh:mm";
97 4 100       30 $tod = $class->new(
    100          
98             hour=>$1, minute=>$2,
99             second => defined($3) ? $3 : 0,
100             nanosecond=>defined($4) ? $4*1e9 : 0);
101             } else {
102 0         0 die "Please specify 'hms'";
103             }
104              
105 4 50       11 die "Unknown parameter(s): ".join(", ", sort keys %args) if keys %args;
106              
107 4         14 $tod;
108             }
109              
110             sub _now {
111 4     4   698 require Time::Local;
112              
113 4         2418 my ($class, $utc, $time) = @_;
114              
115 4 100       62 my @time = $utc ? gmtime($time) : localtime($time);
116 4         13 @time[0..2] = (0,0,0);
117              
118 4 100       19 my $time_bod = $utc ?
119             Time::Local::timegm(@time) : Time::Local::timelocal(@time);
120              
121 4         177 my $tod = $time - $time_bod;
122 4         21 return bless \$tod, $class;
123             }
124              
125             sub now_local {
126 1     1 1 2411 my $class = shift;
127 1         6 $class->_now(0, time());
128             }
129              
130             sub now_utc {
131 1     1 1 2324 my $class = shift;
132 1         5 $class->_now(1, time());
133             }
134              
135             sub hires_now_local {
136 1     1 1 3084 require Time::HiRes;
137              
138 1         1529 my $class = shift;
139 1         9 $class->_now(0, Time::HiRes::time());
140             }
141              
142             sub hires_now_utc {
143 1     1 1 2160 require Time::HiRes;
144              
145 1         4 my $class = shift;
146 1         6 $class->_now(1, Time::HiRes::time());
147             }
148              
149             sub _elements {
150 27     27   66 my $self = shift;
151              
152 27         84 my $n = $$self;
153 27         54 my $hour = int($n / 3600); $n -= $hour*3600;
  27         48  
154 27         59 my $minute = int($n / 60); $n -= $minute*60;
  27         34  
155 27         38 my $second = int($n); $n -= $second;
  27         40  
156 27         71 my $nanosecond = round($n*1e9);
157 27         84 ($hour, $minute, $second, $nanosecond);
158             }
159              
160             sub hour {
161 1     1 1 349 my $self = shift;
162              
163 1         5 my ($hour, $minute, $second, $nanosecond) = $self->_elements;
164 1         8 $hour;
165             }
166              
167             sub minute {
168 1     1 1 3 my $self = shift;
169              
170 1         3 my ($hour, $minute, $second, $nanosecond) = $self->_elements;
171 1         5 $minute;
172             }
173              
174             sub second {
175 1     1 1 2 my $self = shift;
176              
177 1         5 my ($hour, $minute, $second, $nanosecond) = $self->_elements;
178 1         5 $second;
179             }
180              
181             sub nanosecond {
182 2     2 1 5 my $self = shift;
183              
184 2         7 my ($hour, $minute, $second, $nanosecond) = $self->_elements;
185 2         8 $nanosecond;
186             }
187              
188             sub float {
189 11     11 1 17 my $self = shift;
190 11         40 $$self;
191             }
192              
193             sub hms {
194 6     6 1 16 my ($self, $sep) = @_;
195              
196 6   100     26 $sep //= ":";
197 6         13 my ($hour, $minute, $second, $nanosecond) = $self->_elements;
198              
199 6         46 sprintf("%02d%s%02d%s%02d", $hour, $sep, $minute, $sep, $second);
200             }
201              
202             sub stringify {
203 16     16 1 32 my $self = shift;
204              
205 16         30 my ($hour, $minute, $second, $nanosecond) = $self->_elements;
206              
207 16 100       32 if ($nanosecond) {
208 1 50       17 sprintf(
209             "%02d:%02d:%s%.11g",
210             $hour,
211             $minute,
212             $second < 10 ? "0" : "",
213             $second + $nanosecond/1e9);
214             } else {
215 15         89 sprintf("%02d:%02d:%02d", $hour, $minute, $second);
216             }
217             }
218              
219       0 1   sub strftime {
220             # XXX
221             }
222              
223             sub compare {
224 5 100   5 1 20 my $class = ref $_[0] ? undef : shift;
225 5         10 my ($tod1, $tod2) = @_;
226              
227 5 50 33     36 unless ($tod1->can('float') && $tod2->can('float')) {
228 0         0 die "A Date::TimeOfDay object can only be compared to another ".
229             "Date::TimeOfDay object";
230             }
231 5         14 $tod1->float <=> $tod2->float;
232             }
233              
234             sub _compare_overload {
235 1     1   3 my ($tod1, $tod2, $flip) = @_;
236 1 50       11 ($flip ? -1:1) * (compare($tod1, $tod2));
237             }
238              
239             sub _string_compare_overload {
240 3     3   11 my ($tod1, $tod2, $flip) = @_;
241 3 50       13 ($flip ? -1:1) * ("$tod1" cmp "$tod2");
242             }
243              
244             sub _string_equals_overload {
245 2     2   7 my ($tod1, $tod2) = @_;
246 2         5 "$tod1" eq "$tod2";
247             }
248              
249             sub _string_not_equals_overload {
250 2     2   5 my ($tod1, $tod2) = @_;
251 2         5 "$tod1" ne "$tod2";
252             }
253              
254             1;
255             # ABSTRACT: Represent time of day (hh:mm:ss)
256              
257             __END__