File Coverage

blib/lib/JSCalendar/Duration.pm
Criterion Covered Total %
statement 66 70 94.2
branch 40 48 83.3
condition 7 8 87.5
subroutine 6 6 100.0
pod 2 2 100.0
total 121 134 90.3


line stmt bran cond sub pod time code
1             package JSCalendar::Duration;
2             # ABSTRACT: Convert seconds to JSCalendar durations and back
3             $JSCalendar::Duration::VERSION = '0.002';
4 1     1   65677 use strict;
  1         10  
  1         29  
5 1     1   5 use warnings;
  1         2  
  1         38  
6              
7 1     1   6 use Carp qw(croak);
  1         2  
  1         84  
8 1     1   7 use Exporter qw(import);
  1         2  
  1         780  
9              
10             our @EXPORT = qw(seconds_to_duration duration_to_seconds);
11              
12             sub duration_to_seconds {
13 23     23 1 15410 my $input = shift;
14              
15 23 50       61 croak("Usage: duration_to_seconds(\$duration). (Extra args provided: @_)")
16             if @_;
17              
18 23 50       51 croak('Usage: duration_to_seconds($duration)')
19             unless defined $input;
20              
21             # Let's get that out of the way
22 23 100       64 return '0' if $input eq 'P0D';
23              
24 21         29 my $toparse = $input;
25              
26 21         34 my $seconds = 0;
27              
28 21 50       107 unless ($toparse =~ s/^P//) {
29 0         0 croak("Invalid duration '$input', must start with 'P'");
30             }
31              
32 21 100       72 if ($toparse =~ s/^(\d+)D//) {
33 6         18 $seconds += (86400 * $1);
34             }
35              
36 21 100       82 return $seconds unless $toparse;
37              
38 19 50       59 unless ($toparse =~ s/^T//) {
39 0         0 croak("Invalid duration '$input', expected T here: '$toparse'");
40             }
41              
42 19 100       52 if ($toparse =~ s/^(\d+)H//) {
43 4         11 $seconds += (3600 * $1);
44             }
45              
46 19 100       55 if ($toparse =~ s/^(\d+)M//) {
47 7         22 $seconds += (60 * $1);
48             }
49              
50 19 100       78 if ($toparse =~ s/^(\d+(?:\.\d+)?)S//) {
51 17         50 $seconds += $1;
52             }
53              
54 19 50       39 if ($toparse) {
55 0         0 croak("Invalid duration '$input': confused by '$toparse'");
56             }
57              
58 19         123 return $seconds;
59             }
60              
61             sub seconds_to_duration {
62 23     23 1 14241 my $input = shift;
63              
64 23 50       67 croak("Usage: seconds_to_duration(\$seconds). (Extra args provided: @_)")
65             if @_;
66              
67 23 50       50 croak('Usage: seconds_to_duration($seconds)')
68             unless defined $input;
69              
70 23         29 my $toparse = $input;
71              
72 23         32 my $dec;
73              
74 23 100       101 $dec = $1 if $toparse =~ s/\.(\d+)$//;
75              
76             # .1 becomes "", we want 0 after
77 23   100     60 $toparse ||= 0;
78              
79 23 50 66     151 if ($toparse && $toparse !~ /^\d+$/) {
80 0         0 croak("Usage: seconds_to_duration(\$seconds). (Non-number value provided: '$input'");
81             }
82              
83 23         47 my ($durday, $durtime) = ("", "");
84              
85 23         31 my $days = 0;
86              
87 23         67 while ($toparse >= 86400) {
88 9         11 $days++;
89 9         19 $toparse -= 86400;
90             }
91              
92 23 100       47 $durday = "${days}D" if $days;
93              
94 23         28 my $hours = 0;
95              
96 23         48 while ($toparse >= 3600) {
97 48         60 $hours++;
98 48         75 $toparse -= 3600;
99             }
100              
101 23 100       46 $durtime = "${hours}H" if $hours;
102              
103 23         30 my $minutes = 0;
104              
105 23         40 while ($toparse >= 60) {
106 239         293 $minutes++;
107 239         380 $toparse -= 60;
108             }
109              
110 23 100       46 $durtime .= "${minutes}M" if $minutes;
111              
112 23         30 my $seconds = 0;
113              
114 23         43 while ($toparse >= 1) {
115 363         424 $seconds++;
116 363         568 $toparse -= 1;
117             }
118              
119 23 100       44 $durtime .= "${seconds}" if $seconds;
120              
121 23 100       53 if ($dec) {
    100          
122 7 100       19 $durtime .= $durtime ? ".${dec}S" : "0.${dec}S";
123             } elsif ($seconds) {
124 10         16 $durtime .= "S";
125             }
126              
127             # PD
128 23 100 100     91 return "P0D" unless $durday || $durtime;
129              
130 21 100       54 $durtime = "T$durtime" if $durtime;
131              
132 21         130 return "P" . $durday . $durtime;
133             }
134              
135             1;
136              
137             =pod
138              
139             =encoding UTF-8
140              
141             =head1 NAME
142              
143             JSCalendar::Duration - Convert seconds to JSCalendar durations and back
144              
145             =head1 VERSION
146              
147             version 0.002
148              
149             =head1 SYNOPSIS
150              
151             use JSCalendar::Duration qw(
152             seconds_to_duration
153             duration_to_seconds
154             );
155              
156             # 104403.1
157             my $seconds = duration_to_seconds("P1DT5H3.1S");
158              
159             # P1D
160             my $duration = seconds_to_duration('86400');
161              
162             =head1 DESCRIPTION
163              
164             This module converts between a duration of time as specified by seconds and
165             a JSCalendar duration (L).
166              
167             =head1 EXPORTS
168              
169             =head2 seconds_to_duration
170              
171             my $duration = seconds_to_duration("86401.2");
172              
173             Converts seconds to a JSCalendar duration representation.
174              
175             =head2 duration_to_seconds
176              
177             my $seconds = duration_to_seconds("P1DT4H");
178              
179             Converts a JSCalendar duration to seconds.
180              
181             =head1 SEE ALSO
182              
183             =over 4
184              
185             =item L
186              
187             The JSCalendar duration spec.
188              
189             =back
190              
191             =head1 AUTHOR
192              
193             Matthew Horsfall
194              
195             =head1 CONTRIBUTOR
196              
197             =for stopwords Mohammad S Anwar
198              
199             Mohammad S Anwar
200              
201             =head1 COPYRIGHT AND LICENSE
202              
203             This software is copyright (c) 2018 by Matthew Horsfall.
204              
205             This is free software; you can redistribute it and/or modify it under
206             the same terms as the Perl 5 programming language system itself.
207              
208             =cut
209              
210             __END__