File Coverage

blib/lib/Time/Business.pm
Criterion Covered Total %
statement 26 74 35.1
branch 0 20 0.0
condition 3 16 18.7
subroutine 5 7 71.4
pod 3 3 100.0
total 37 120 30.8


line stmt bran cond sub pod time code
1             package Time::Business;
2 1     1   27232 use strict;
  1         2  
  1         52  
3              
4             BEGIN {
5 1     1   6 use Exporter ();
  1         2  
  1         21  
6 1     1   5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS @starttime @stoptime);
  1         5  
  1         137  
7 1     1   2 $VERSION = '0.18';
8 1         22 @ISA = qw(Exporter);
9             #Give a hoot don't pollute, do not export more than needed by default
10 1         2 @EXPORT = qw();
11 1         7 @EXPORT_OK = qw();
12 1         901 %EXPORT_TAGS = ();
13             }
14              
15              
16             sub new
17             {
18            
19            
20 1     1 1 16 my ($class, $parameters) = @_;
21              
22 1   33     12 my $self = bless ({}, ref ($class) || $class);
23            
24 1   50     14 $self->{STARTTIME} = $parameters->{STARTTIME} || "00:00:00";
25 1   50     7 $self->{STOPTIME} = $parameters->{STOPTIME} || "00:00:00";
26              
27 1         2 foreach my $workday (@{$parameters->{WORKDAYS}}){
  1         11  
28 0         0 $self->{WORKDAYS}->{$workday}=1;
29             }
30            
31 1         6 @starttime = split /:/, $self->{STARTTIME};
32 1         6 @stoptime = split /:/, $self->{STOPTIME};
33            
34 1         7 $self->{worksecs} = ($stoptime[0] - $starttime[0]) * 3600 + ($stoptime[1] - $starttime[1]) * 60;
35 1         5 $self->{startworkmin} = $starttime[0] * 60 + $starttime[1];
36 1         4 $self->{stopworkmin} = $stoptime[0] * 60 + $stoptime[1];
37            
38 1         4 return $self;
39            
40             }
41              
42             sub duration {
43            
44 0     0 1   my $self =shift;
45 0           my($start,$stop) = @_;
46            
47 0           my $duration = $stop - $start;
48            
49 0           my ($ssec,$smin,$shour,$smday,$smon,$syear,$swday,$syday,$sisdst) = localtime($start);
50 0           my ($esec,$emin,$ehour,$emday,$emon,$eyear,$ewday,$eyday,$eisdst) = localtime($stop);
51 0           my ($dsec,$dmin,$dhour,$dmday,$dmon,$dyear,$dwday,$dyday,$disdst) = localtime($duration);
52              
53 0           my $daysin;
54             my $daysleft;
55              
56 0           $daysleft = $dyday % 7;
57              
58 0 0         if($dyday >= 2) {
59              
60 0           $daysin = int(($dyday) / 7) * 5 ;
61 0           $daysleft = $dyday % 7;
62            
63 0 0         if($daysleft==0) {
64 0           $daysin = $daysin - 1;
65 0           $daysleft++;
66             }
67            
68 0           my $startloop = ($swday)%7+1;
69 0           my $endloop = $startloop + $daysleft - 1;
70            
71 0           for (my $i = $startloop;$i<$endloop;$i++) {
72 0           my $wday = $i%7;
73 0 0         if(defined $self->{WORKDAYS}->{$wday}) {
74 0           $daysin++;
75            
76             }
77             }
78             }
79            
80            
81             # Count valid hours in first day
82 0           my $seconds = 0;
83 0 0         if($duration > ($daysin*86400) ) {
84            
85 0 0         if( defined $self->{WORKDAYS}->{$swday}) {
86            
87 0           my $end_seconds = $ehour * 3600 + $emin * 60 + $esec;
88 0           my $start_seconds = $shour * 3600 + $smin * 60 + $ssec;
89 0           my $start_day = $starttime[0] * 3600 + $starttime[1] * 60;
90 0           my $stop_day = $stoptime[0] * 3600 + $stoptime[1] * 60;
91            
92 0 0 0       if(($end_seconds > $stop_day) || $eyday - $syday >= 1 ) {
93 0           $end_seconds = $stop_day;
94             }
95            
96 0 0 0       if($start_seconds < $stop_day && $start_seconds > $start_day ) {
97 0           $seconds = $end_seconds - $start_seconds;
98            
99             }
100            
101             }
102            
103             # Count valid hours in last day
104            
105 0 0 0       if(($eyday - $syday >= 1) && defined $self->{WORKDAYS}->{$ewday} ) {
106            
107 0 0         if($ehour * 60 + $emin >= $self->{startworkmin}) {
108            
109            
110 0           my $start_seconds = $starttime[0] * 3600 + $starttime[1] * 60;
111 0           my $end_seconds = $ehour * 3600 + $emin * 60 + $esec;
112 0           my $stop_day = $stoptime[0] * 3600 + $stoptime[1] * 60;
113              
114 0 0         if($end_seconds > $stop_day) {
115 0           $end_seconds = $stop_day;
116             }
117              
118 0           $seconds = $seconds + ($end_seconds - $start_seconds);
119            
120             }
121              
122             }
123             }
124            
125            
126 0           $seconds = $seconds + $daysin * $self->{worksecs};
127 0           return $seconds;
128            
129             }
130              
131             sub workTimeString {
132            
133 0     0 1   my $self = shift;
134 0           my $seconds = shift;
135            
136            
137            
138 0           my $days = int($seconds/$self->{worksecs});
139 0           my $minutes = int($seconds%$self->{worksecs});
140 0           my ($ssec,$smin,$shour,$smday,$smon,$syear,$swday,$syday,$sisdst) = gmtime($minutes);
141 0           return "$days days $shour hours $smin minutes";
142             }
143              
144              
145             =head1 NAME
146              
147             Time::Business - Business Time Between Two Times
148              
149             =head1 SYNOPSIS
150              
151             use Time::Business;
152            
153             my $btime = Time::Business->new({
154             WORKDAYS => [1,2,3,4,5],
155             STARTTIME => '9:00',
156             STOPTIME => '17:00',
157             });
158              
159             $begin=time();
160             $end=time()+86400;
161             $seconds = $btime->calctime($begin,$end);
162              
163             =head1 DESCRIPTION
164              
165             Calculates the number of business seconds between two dates (specified in
166             epoch seconds) given a list of working days and start and end times.
167              
168             =head1 METHODS
169              
170             =head2 new({....})
171              
172            
173             Setup a Time::Business object, passing the working time parameters.
174             eg.
175              
176             my $btime = Time::Business->new({
177             WORKDAYS => [1,2,3,4,5],
178             STARTTIME => '9:00',
179             STOPTIME => '17:00',
180             });
181              
182             where WORKDAYS is specified as a list of 0..6 where Sun is 0 and Sat is 6.
183              
184              
185             =head2 duration($begin,$end) - Return number of business seconds.
186            
187             Returns the number of business seconds between $begin and $end (seconds since epoch)
188             given the parameters specified in the Time::Business->new.
189              
190             =head2 workTimeString($seconds) - Convert seconds to human readable work time.
191              
192             Converts the $seconds given to a string of the form "n days n hours n minutes".
193             NOTE: This conversion is based on business hours so one day is one working
194             day, not one 24 hour day. Useful for reports etc.
195              
196             =head1 SUPPORT
197              
198              
199              
200             =head1 AUTHOR
201              
202             David Peters
203             CPAN ID: DAVIDP
204             davidp@electronf.com
205             http://www.electronf.com
206              
207             =head1 COPYRIGHT
208              
209             This program is free software; you can redistribute
210             it and/or modify it under the same terms as Perl itself.
211              
212             The full text of the license can be found in the
213             LICENSE file included with this module.
214              
215              
216             =head1 SEE ALSO
217              
218             perl(1).
219              
220             =cut
221              
222             #################### main pod documentation end ###################
223              
224              
225             1;
226             # The preceding line will help the module return a true value
227