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