File Coverage

blib/lib/Timer/Simple.pm
Criterion Covered Total %
statement 62 66 93.9
branch 36 40 90.0
condition 11 20 55.0
subroutine 16 16 100.0
pod 11 11 100.0
total 136 153 88.8


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