File Coverage

blib/lib/Time/Duration/Parse.pm
Criterion Covered Total %
statement 31 31 100.0
branch 8 8 100.0
condition n/a
subroutine 6 6 100.0
pod 1 1 100.0
total 46 46 100.0


line stmt bran cond sub pod time code
1             package Time::Duration::Parse;
2             $Time::Duration::Parse::VERSION = '0.16';
3 3     3   212891 use 5.006;
  3         31  
4 3     3   18 use strict;
  3         6  
  3         73  
5 3     3   15 use warnings;
  3         11  
  3         104  
6              
7 3     3   20 use Carp;
  3         3  
  3         229  
8 3     3   19 use Exporter 5.57 qw(import);
  3         70  
  3         1772  
9             our @EXPORT = qw( parse_duration );
10              
11             # This map is taken from Cache and Cache::Cache
12             # map of expiration formats to their respective time in seconds
13             my %Units = ( map(($_, 1), qw(s second seconds sec secs)),
14             map(($_, 60), qw(m minute minutes min mins)),
15             map(($_, 60*60), qw(h hr hrs hour hours)),
16             map(($_, 60*60*24), qw(d day days)),
17             map(($_, 60*60*24*7), qw(w week weeks)),
18             map(($_, 60*60*24*30), qw(M month months mo mon mons)),
19             map(($_, 60*60*24*365), qw(y year years)) );
20              
21             sub parse_duration {
22 2050     2050 1 1229954 my $timespec = shift;
23              
24             # You can have an optional leading '+', which has no effect
25 2050         4709 $timespec =~ s/^\s*\+\s*//;
26              
27             # Treat a plain number as a number of seconds (and parse it later)
28 2050 100       10676 if ($timespec =~ /^\s*(-?\d+(?:[.,]\d+)?)\s*$/) {
29 5         17 $timespec = "$1s";
30             }
31              
32             # Convert hh:mm(:ss)? to something we understand
33 2050         3686 $timespec =~ s/\b(\d+):(\d\d):(\d\d(\.\d+)?)\b/$1h $2m $3s/g;
34 2050         2967 $timespec =~ s/\b(\d+):(\d\d)\b/$1h $2m/g;
35              
36 2050         3634 my $duration = 0;
37 2050         10938 while ($timespec =~ s/^\s*(-?\d+(?:[.,]\d+)?)\s*([a-zA-Z]+)(?:\s*(?:,|and)\s*)*//i) {
38 6184         16752 my($amount, $unit) = ($1, $2);
39 6184 100       12734 $unit = lc($unit) unless length($unit) == 1;
40              
41 6184 100       12736 if (my $value = $Units{$unit}) {
42 6182         9529 $amount =~ s/,/./;
43 6182         26507 $duration += $amount * $value;
44             } else {
45 2         258 Carp::croak "Unknown timespec: $1 $2";
46             }
47             }
48              
49 2048 100       4088 if ($timespec =~ /\S/) {
50 1         85 Carp::croak "Unknown timespec: $timespec";
51             }
52              
53 2047         11107 return sprintf "%.0f", $duration;
54             }
55              
56             1;
57             __END__