File Coverage

blib/lib/Time/Left.pm
Criterion Covered Total %
statement 62 63 98.4
branch 33 36 91.6
condition 14 21 66.6
subroutine 22 22 100.0
pod 8 8 100.0
total 139 150 92.6


line stmt bran cond sub pod time code
1 5     5   608929 use 5.010;
  5         19  
2 5     5   32 use strict;
  5         31  
  5         150  
3 5     5   24 use warnings;
  5         43  
  5         591  
4              
5             package Time::Left;
6             our $VERSION = '1.000';
7              
8 5     5   36 use Exporter qw(import);
  5         11  
  5         220  
9 5     5   24 use Scalar::Util qw(looks_like_number);
  5         10  
  5         279  
10 5     5   49 use Time::HiRes qw(clock_gettime);
  5         23  
  5         45  
11              
12             use constant CLOCK =>
13 5         31 eval { Time::HiRes::CLOCK_MONOTONIC_RAW() } //
14 5   33     8 eval { Time::HiRes::CLOCK_MONOTONIC() } //
  0   33     0  
15 5     5   698 Time::HiRes::CLOCK_REALTIME();
  5         10  
16              
17             use overload
18 5         30 bool => 'active',
19             '!' => 'expired',
20             '0+' => '_numify',
21             '<=>' => '_compare',
22             '""' => '_stringify',
23             cmp => '_strcmp',
24             nomethod => '_nomethod',
25 5     5   4255 ;
  5         9544  
26              
27             our @EXPORT_OK = qw(to_seconds time_left);
28              
29 4 50   4   702 sub _die { exists(&Carp::croak) ? goto &Carp::croak : die "@_\n" }
30              
31             ### Functions
32              
33             sub to_seconds {
34 26     26 1 211681 my ($t) = @_;
35 26 100       123 unless (looks_like_number($t)) {
36             return undef
37 22 100 100     267 unless $t =~ /^(.+)([smhd])$/
38             and looks_like_number($1);
39 19         45 $t = $1;
40 19 100       126 if ($2 eq 'm') { $t *= 60 }
  2 100       4  
    100          
41 1         6 elsif ($2 eq 'h') { $t *= 3600 }
42 1         3 elsif ($2 eq 'd') { $t *= 86400 }
43             }
44 23         129 return $t;
45             }
46              
47             sub time_left {
48 24     24 1 381673 my ($t) = @_;
49 24 100 66     109 return defined($t) ?
50             Time::Left->new(to_seconds($t) // _die("time_left: invalid duration '$_[0]'")) :
51             Time::Left->new($t);
52             }
53              
54             ### Methods
55              
56             sub new {
57 27     27 1 232923 my ($class, $time) = @_;
58 27 100 100     143 _die("${class}->new: invalid time '$time'")
59             unless looks_like_number($time // 0);
60 26 100       141 $time += clock_gettime(CLOCK)
61             if defined $time;
62 26   33     210 return bless(\$time, ref($class)||$class);
63             }
64              
65 23 100   23 1 41519 sub remaining { defined(${$_[0]}) ? ${$_[0]} - clock_gettime(CLOCK) : undef }
  23         2534  
  21         282  
66 37 100   37 1 760351 sub active { defined(${$_[0]}) ? ${$_[0]} > clock_gettime(CLOCK) : 1 }
  37         243  
  34         325  
67 7 100   7 1 201510 sub expired { defined(${$_[0]}) ? ${$_[0]} <= clock_gettime(CLOCK) : !1 }
  7         32  
  6         96  
68 6     6 1 20 sub is_limited { defined(${$_[0]}) }
  6         34  
69 2     2 1 7 sub abort { ${$_[0]} = clock_gettime(CLOCK) }
  2         4  
70              
71 1     1   11 sub _numify { _die("Can't numify Time::Left") }
72 1     1   478 sub _nomethod { _die("Time::Left does not overload '$_[3]'") }
73 12 100   12   136 sub _stringify { defined(${$_[0]}) ? sprintf("%.3f", $_[0]->remaining) : 'Inf' }
  12         80  
74 2 100   2   16 sub _strcmp { ($_[0]->_stringify cmp (ref($_[1]) ? $_[1]->_stringify : $_[1])) * ($_[2] ? -1 : 1) }
    50          
75             sub _compare {
76 13     13   44 my ($a, $b, $swap) = @_;
77 13   100     61 $a = $$a // 'Inf';
78 13 50 100     65 $b = ref($b) ? $$b // 'Inf' : defined($b) ? $b + clock_gettime(CLOCK) : 'Inf';
    100          
79 13 100       156 return $swap ? $b <=> $a : $a <=> $b;
80             }
81              
82             1;
83             __END__