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
|
|
|
|
|
|
|
|