File Coverage

blib/lib/Timer/Simple.pm
Criterion Covered Total %
statement 63 67 94.0
branch 36 40 90.0
condition 11 20 55.0
subroutine 17 17 100.0
pod 11 11 100.0
total 138 155 89.0


line stmt bran cond sub pod time code
1             # vim: set sw=2 sts=2 ts=2 expandtab smarttab:
2             #
3             # This file is part of Timer-Simple
4             #
5             # This software is copyright (c) 2011 by Randy Stauner.
6             #
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             #
10 2     2   3963 use strict;
  2         7  
  2         172  
11 2     2   13 use warnings;
  2         4  
  2         155  
12              
13             package Timer::Simple;
14             # git description: v1.004-5-gb873a31
15             $Timer::Simple::VERSION = '1.005';
16             BEGIN {
17 2     2   40 $Timer::Simple::AUTHORITY = 'cpan:RWSTAUNER';
18             }
19             # ABSTRACT: Small, simple timer (stopwatch) object
20              
21 2     2   11 use Carp qw(croak carp); # core
  2         3  
  2         213  
22             use overload # core
23 2         25 '""' => \&string,
24             '0+' => \&elapsed,
25 2     2   11 fallback => 1;
  2         4  
26              
27              
28             sub new {
29 7     7 1 4506 my $class = shift;
30 0         0 my $self = {
31             start => 1,
32             string => 'short',
33             hires => HIRES(),
34 7 50       22 @_ == 1 ? %{$_[0]} : @_,
35             };
36              
37 7 50       22 if( $self->{format} ){
38 0         0 carp("$class option 'format' is deprecated. Use 'hms' (or 'string')");
39 0   0     0 $self->{hms} ||= delete $self->{format};
40             }
41 7   33     36 $self->{hms} ||= default_format_spec($self->{hires});
42              
43 7         22 bless $self, $class;
44              
45 7 100       153 $self->start
46             if $self->{start};
47              
48 7         19 return $self;
49             }
50              
51              
52             sub elapsed {
53 32     32 1 755919 my ($self) = @_;
54              
55 32 100       978 if( !defined($self->{started}) ){
56 3         6590 croak("Timer never started!");
57             }
58              
59             # if stop() was called, use that time, otherwise "now"
60 29 100       285 my $elapsed = defined($self->{stopped})
61             ? $self->{stopped}
62             : $self->time;
63              
64 29 100       147 return $self->{hires}
65             ? Time::HiRes::tv_interval($self->{started}, $elapsed)
66             : $elapsed - $self->{started};
67             }
68              
69              
70             sub hms {
71 9     9 1 4646 my ($self, $format) = @_;
72              
73 9         23 my ($h, $m, $s) = separate_hms($self->elapsed);
74              
75             return wantarray
76 9 100 66     192 ? ($h, $m, $s)
77             : sprintf(($format || $self->{hms}), $h, $m, $s);
78             }
79              
80              
81             sub start {
82 7     7 1 1171 my ($self) = @_;
83              
84             # don't use an old stopped time if we're restarting
85 7         15 delete $self->{stopped};
86              
87 7         11 $self->{started} = $self->time;
88             }
89              
90              
91             sub stop {
92 7     7 1 281432 my ($self) = @_;
93 7 100       52 $self->{stopped} = $self->time
94             # don't change the clock if it's already stopped
95             if !defined($self->{stopped});
96             # natural return value would be elapsed() but don't compute it in void context
97 7 100       40 return $self->elapsed
98             if defined wantarray;
99             }
100              
101              
102             sub string {
103 12     12 1 4462 my ($self, $format) = @_;
104 12   66     48 $format ||= $self->{string};
105              
106             # if it's a method name or a coderef delegate to it
107 12 100 100     143 return scalar $self->$format()
      66        
108             if $self->can($format)
109             || ref($format) eq 'CODE'
110             || overload::Method($format, '&{}');
111              
112             # cache the time so that all formats show the same (in case it isn't stopped)
113 7         2366 my $seconds = $self->elapsed;
114              
115 7         70 my $string;
116 7 100       39 if( $format eq 'short' ){
    100          
    50          
117 4         14 $string = sprintf('%ss (' . $self->{hms} . ')', $seconds, separate_hms($seconds));
118             }
119             elsif( $format eq 'rps' ){
120 1         10 my $elapsed = sprintf '%f', $seconds;
121 1 50       12 my $rps = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
122 1         4 $string = "${elapsed}s ($rps/s)";
123             }
124             elsif( $format =~ /human|full/ ){
125             # human
126 2         6 $string = sprintf('%d hours %d minutes %s seconds', separate_hms($seconds));
127 2 100       12 $string = $seconds . ' seconds (' . $string . ')'
128             if $format eq 'full';
129             }
130             else {
131 0         0 croak("Unknown format: $format");
132             }
133 7         42 return $string;
134             }
135              
136              
137             sub time {
138 21 100   21 1 159 return $_[0]->{hires}
139             ? [ Time::HiRes::gettimeofday() ]
140             : time;
141             }
142              
143             {
144             # aliases
145 2     2   2695 no warnings 'once';
  2         5  
  2         1204  
146             *restart = \&start;
147             }
148              
149             # package functions
150              
151              
152             {
153             # only perform the check once, but don't perform the check until required
154             my $HIRES;
155             sub HIRES () { ## no critic Prototypes
156 8 100 50 8 1 24 $HIRES = (do { local $@; eval { require Time::HiRes; 1; } } || '')
157             if !defined($HIRES);
158 8         47 return $HIRES;
159             }
160             }
161              
162              
163             sub default_format_spec {
164 14 100   14 1 1017 my ($fractional) = @_ ? @_ : HIRES();
165             # float: 9 (width) - 6 (precision) - 1 (dot) == 2 digits before decimal point
166 14 100       109 return '%02d:%02d:' . ($fractional ? '%09.6f' : '%02d');
167             }
168              
169              
170             sub format_hms {
171             # if only one argument was provided assume its seconds and split it
172 4 100   4 1 17 my ($h, $m, $s) = (@_ == 1 ? separate_hms(@_) : @_);
173              
174 4         11 return sprintf(default_format_spec(int($s) != $s), $h, $m, $s);
175             }
176              
177              
178             sub separate_hms {
179 19     19 1 103 my ($s) = @_;
180              
181             # find the number of whole hours, then subtract them
182 19         1787 my $h = int($s / 3600);
183 19         37 $s -= $h * 3600;
184             # find the number of whole minutes, then subtract them
185 19         28 my $m = int($s / 60);
186 19         23 $s -= $m * 60;
187              
188 19         116 return ($h, $m, $s);
189             }
190              
191             1;
192              
193             __END__