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.14';
3 3     3   168083 use 5.006;
  3         27  
4 3     3   14 use strict;
  3         5  
  3         62  
5 3     3   12 use warnings;
  3         12  
  3         87  
6              
7 3     3   15 use Carp;
  3         4  
  3         194  
8 3     3   1320 use Exporter::Lite;
  3         1556  
  3         14  
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 2047     2047 1 935148 my $timespec = shift;
23              
24             # You can have an optional leading '+', which has no effect
25 2047         3555 $timespec =~ s/^\s*\+\s*//;
26              
27             # Treat a plain number as a number of seconds (and parse it later)
28 2047 100       8603 if ($timespec =~ /^\s*(-?\d+(?:[.,]\d+)?)\s*$/) {
29 5         12 $timespec = "$1s";
30             }
31              
32             # Convert hh:mm(:ss)? to something we understand
33 2047         2819 $timespec =~ s/\b(\d+):(\d\d):(\d\d)\b/$1h $2m $3s/g;
34 2047         2232 $timespec =~ s/\b(\d+):(\d\d)\b/$1h $2m/g;
35              
36 2047         2454 my $duration = 0;
37 2047         8366 while ($timespec =~ s/^\s*(-?\d+(?:[.,]\d+)?)\s*([a-zA-Z]+)(?:\s*(?:,|and)\s*)*//i) {
38 6141         13667 my($amount, $unit) = ($1, $2);
39 6141 100       9849 $unit = lc($unit) unless length($unit) == 1;
40              
41 6141 100       9741 if (my $value = $Units{$unit}) {
42 6139         7250 $amount =~ s/,/./;
43 6139         20673 $duration += $amount * $value;
44             } else {
45 2         223 Carp::croak "Unknown timespec: $1 $2";
46             }
47             }
48              
49 2045 100       3250 if ($timespec =~ /\S/) {
50 1         60 Carp::croak "Unknown timespec: $timespec";
51             }
52              
53 2044         8261 return sprintf "%.0f", $duration;
54             }
55              
56             1;
57             __END__