File Coverage

blib/lib/Date/TimeOfDay.pm
Criterion Covered Total %
statement 114 118 96.6
branch 41 58 70.6
condition 11 20 55.0
subroutine 26 27 96.3
pod 16 16 100.0
total 208 239 87.0


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