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.15';
3 3     3   205512 use 5.006;
  3         30  
4 3     3   29 use strict;
  3         7  
  3         77  
5 3     3   15 use warnings;
  3         14  
  3         101  
6              
7 3     3   17 use Carp;
  3         6  
  3         192  
8 3     3   1455 use Exporter::Lite;
  3         2097  
  3         25  
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 1226035 my $timespec = shift;
23              
24             # You can have an optional leading '+', which has no effect
25 2050         4823 $timespec =~ s/^\s*\+\s*//;
26              
27             # Treat a plain number as a number of seconds (and parse it later)
28 2050 100       10842 if ($timespec =~ /^\s*(-?\d+(?:[.,]\d+)?)\s*$/) {
29 5         17 $timespec = "$1s";
30             }
31              
32             # Convert hh:mm(:ss)? to something we understand
33 2050         3921 $timespec =~ s/\b(\d+):(\d\d):(\d\d(\.\d+)?)\b/$1h $2m $3s/g;
34 2050         2836 $timespec =~ s/\b(\d+):(\d\d)\b/$1h $2m/g;
35              
36 2050         3103 my $duration = 0;
37 2050         10827 while ($timespec =~ s/^\s*(-?\d+(?:[.,]\d+)?)\s*([a-zA-Z]+)(?:\s*(?:,|and)\s*)*//i) {
38 6132         16534 my($amount, $unit) = ($1, $2);
39 6132 100       13125 $unit = lc($unit) unless length($unit) == 1;
40              
41 6132 100       12636 if (my $value = $Units{$unit}) {
42 6130         9158 $amount =~ s/,/./;
43 6130         27163 $duration += $amount * $value;
44             } else {
45 2         298 Carp::croak "Unknown timespec: $1 $2";
46             }
47             }
48              
49 2048 100       3898 if ($timespec =~ /\S/) {
50 1         80 Carp::croak "Unknown timespec: $timespec";
51             }
52              
53 2047         10989 return sprintf "%.0f", $duration;
54             }
55              
56             1;
57             __END__