/[Time-Available]/Available.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /Available.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6 by dpavlin, Sun Oct 5 22:26:54 2003 UTC revision 1.11 by dpavlin, Sun Oct 12 19:17:29 2003 UTC
# Line 3  package Time::Available; Line 3  package Time::Available;
3  use 5.001;  use 5.001;
4  use strict;  use strict;
5  use warnings;  use warnings;
6    use Carp;
7    use Time::Local;
8    
9  require Exporter;  require Exporter;
10    
# Line 31  our @EXPORT_OK = ( Line 33  our @EXPORT_OK = (
33    
34  our @EXPORT;    # don't export anything by default!  our @EXPORT;    # don't export anything by default!
35    
36  our $VERSION = '0.01';  our $VERSION = '0.02';
37    
38  # define some constants used later  # define some constants used later
39  use constant DAY_MONDAY    => 0x01;  use constant DAY_MONDAY    => 0x01;
# Line 59  sub new { Line 61  sub new {
61          $self->{ARGS} = {@_};          $self->{ARGS} = {@_};
62          $debug = $self->{ARGS}->{DEBUG};          $debug = $self->{ARGS}->{DEBUG};
63    
64          die("need start time") if (! $self->{ARGS}->{start});          croak("need start time") if (! $self->{ARGS}->{start});
65    
66          # calc start and stop seconds          # calc start and stop seconds
67          my ($hh,$mm,$ss) = split(/:/,$self->{ARGS}->{start},3);          my ($hh,$mm,$ss) = split(/:/,$self->{ARGS}->{start},3);
68          print STDERR "new: start time ",$hh||0,":",$mm||0,":",$ss||0,"\n" if ($debug);          print STDERR "new: start time ",$hh||0,":",$mm||0,":",$ss||0,"\n" if ($debug);
69          my $s = $hh * 3600 || die("need at least hour specified for start time");          croak("need at least hour specified for start time") if (! $hh);
70          $s += $mm * 60 if ($mm);          $mm |= 0;
71          $s += $ss if ($ss);          $ss |= 0;
72          $self->{start} = $s;          $self->{start_arr} = [$ss,$mm,$hh];
73    
74            my $start = $hh;
75            $start *= 60;
76            $start += $mm;
77            $start *= 60;
78            $start += $ss;
79    
80          die("need end time") if (! $self->{ARGS}->{end});          croak("need end time") if (! $self->{ARGS}->{end});
81    
82          ($hh,$mm,$ss) = split(/:/,$self->{ARGS}->{end},3);          ($hh,$mm,$ss) = split(/:/,$self->{ARGS}->{end},3);
83          print STDERR "new: end time ",$hh||0,":",$mm||0,":",$ss||0,"\n" if ($debug);          print STDERR "new: end time ",$hh||0,":",$mm||0,":",$ss||0,"\n" if ($debug);
84          $s = $hh * 3600 || die("need at least hour specified for end time");          croak("need at least hour specified for end time") if (! $hh);
85          $s += $mm * 60 if ($mm);          $mm |= 0;
86          $self->{end} = $s;          $ss |= 0;
87            $self->{end_arr} = [$ss,$mm,$hh];
88    
89            my $end = $hh;
90            $end *= 60;
91            $end += $mm;
92            $end *= 60;
93            $end += $ss;
94    
95          die("need dayMask specified") if (! $self->{ARGS}->{dayMask});          croak("need dayMask specified") if (! $self->{ARGS}->{dayMask});
96    
97          $self->{dayMask} = $self->{ARGS}->{dayMask};          $self->{dayMask} = $self->{ARGS}->{dayMask};
98    
99            # over midnight?
100            if ($start > $end) {
101                    $self->{sec_in_interval} = (86400 - $start + $end);
102            } else {
103                    $self->{sec_in_interval} = ($end - $start);
104            }
105          $self ? return $self : return undef;          $self ? return $self : return undef;
106  }  }
107    
   
   
108  #  #
109  # this sub (originally from Time::Avail) will return if day is applicable  # this sub (originally from Time::Avail) will return if day is applicable
110  #  #
# Line 119  sub _dayOk($) { Line 138  sub _dayOk($) {
138          return $dayOk;          return $dayOk;
139  }  }
140    
141    #
142    # calculate start and end of interval in given day
143    #
144    
145    sub _start {
146            my $self = shift;
147            my $t = shift || croak "_start needs timestap";
148    
149            my @lt = localtime($t);
150            $lt[0] = $self->{start_arr}[0];
151            $lt[1] = $self->{start_arr}[1];
152            $lt[2] = $self->{start_arr}[2];
153            return timelocal(@lt);
154    }
155    
156    sub _end {
157            my $self = shift;
158            my $t = shift || croak "_end needs timestap";
159    
160            my @lt = localtime($t);
161            $lt[0] = $self->{end_arr}[0];
162            $lt[1] = $self->{end_arr}[1];
163            $lt[2] = $self->{end_arr}[2];
164            return timelocal(@lt);
165    }
166    
167  #  #
168  # this will return number of seconds that service is available if passed  # this will return number of seconds that service is available if passed
# Line 128  sub _dayOk($) { Line 172  sub _dayOk($) {
172  sub uptime {  sub uptime {
173          my $self = shift;          my $self = shift;
174    
175          my $time = shift || die "need uptime timestamp to calculate uptime";          my $time = shift || croak "need uptime timestamp to calculate uptime";
176    
177          # calculate offset -- that is number of seconds since midnight          # calculate offset -- that is number of seconds since midnight
178          my @lt = gmtime($time);          my @lt = localtime($time);
179    
180          # check if day falls into dayMask          # check if day falls into dayMask
181          return 0 if (! $self->_dayOk($lt[6]) );          return 0 if (! $self->_dayOk($lt[6]) );
182    
         my $offset = $lt[2];    # hour  
         $offset *= 60;          # convert to minutes  
         $offset += $lt[1];      # minutes  
         $offset *= 60;          # convert to seconds  
         $offset += $lt[0];  
   
183          my $s=0;          my $s=0;
184    
185          my $start = $self->{start};          my $start = $self->_start($time);
186          my $end = $self->{end};          my $end = $self->_end($time);
187    
188          print STDERR "start: $start end: $end time: $offset [$lt[2]:$lt[1]:$lt[0]]\n" if ($debug);          print STDERR "start: $start end: $end time: $time [$lt[2]:$lt[1]:$lt[0]]\n" if ($debug);
189    
190          if ( $end > $start ) {          if ( $end > $start ) {
191                  if ($offset < $start) {                  if ($time < $start) {
192                          $s = $end - $start;                          $s = $end - $start;
193                  } elsif ($offset < $end) {                  } elsif ($time < $end) {
194                          $s = $end - $offset;                          $s = $end - $time;
195                  }                  }
196          } elsif ( $start > $end ) {     # over midnight          } elsif ( $start > $end ) {     # over midnight
197                  if ( $offset < $end ) {                  if ( $time < $end ) {
198                          if ( $offset < $start) {                          if ( $time < $start) {
199                                  $s = SEC_PER_DAY - $start + $end - $offset;                                  $s = SEC_PER_DAY - $start + $end - $time;
200                          } else {                          } else {
201                                  $s = SEC_PER_DAY - $start + $end;                                  $s = SEC_PER_DAY - $start + $end;
202                          }                          }
203                  } else {                  } else {
204                          if ( $offset < $start ) {                          if ( $time < $start ) {
205                                  $s = SEC_PER_DAY - $start;                                  $s = SEC_PER_DAY - $start;
206                          } else {                          } else {
207                                  $s = SEC_PER_DAY - $offset;                                  $s = SEC_PER_DAY - $time;
208                          }                          }
209                  }                  }
210          }          }
# Line 182  sub uptime { Line 220  sub uptime {
220  sub downtime {  sub downtime {
221          my $self = shift;          my $self = shift;
222    
223          my $time = shift || die "need downtime timestamp to calculate uptime";          my $time = shift || croak "need downtime timestamp to calculate uptime";
224    
225          # calculate offset -- that is number of seconds since midnight          # calculate offset -- that is number of seconds since midnight
226          my @lt = gmtime($time);          my @lt = localtime($time);
227    
228          # check if day falls into dayMask          # check if day falls into dayMask
229          return 0 if (! $self->_dayOk($lt[6]) );          return 0 if (! $self->_dayOk($lt[6]) );
230    
         my $offset = $lt[2];    # hour  
         $offset *= 60;          # convert to minutes  
         $offset += $lt[1];      # minutes  
         $offset *= 60;          # convert to seconds  
         $offset += $lt[0];  
   
231          my $s=0;          my $s=0;
232    
233          my $start = $self->{start};          my $start = $self->_start($time);
234          my $end = $self->{end};          my $end = $self->_end($time);
235    
236          print STDERR "start: $start end: $end time: $offset [$lt[2]:$lt[1]:$lt[0]]\n" if ($debug);          print STDERR "start: $start end: $end time: $time [$lt[2]:$lt[1]:$lt[0]]\n" if ($debug);
237    
238          if ( $end > $start ) {          if ( $end > $start ) {
239                  if ($offset > $start && $offset <= $end) {                  if ($time > $start && $time <= $end) {
240                          $s = $end - $offset;                          $s = $end - $time;
241                  } elsif ($offset < $start) {                  } elsif ($time < $start) {
242                          $s = $end - $start;                          $s = $end - $start;
243                  }                  }
244          } elsif ( $start > $end ) {     # over midnight          } elsif ( $start > $end ) {     # over midnight
245                  if ( $offset < $end ) {                  if ( $time < $end ) {
246                          if ( $offset < $start) {                          if ( $time < $start) {
247                                  $s = $offset;                                  $s = $time;
248                          } else {                          } else {
249                                  $s = 0;                                  $s = 0;
250                          }                          }
251                  } else {                  } else {
252                          if ( $offset < $start ) {                          if ( $time < $start ) {
253                                  $s = SEC_PER_DAY - $end;                                  $s = SEC_PER_DAY - $end;
254                          } else {                          } else {
255                                  $s = SEC_PER_DAY - $end + $start - $offset;                                  $s = SEC_PER_DAY - $end + $start - $time;
256                          }                          }
257                  }                  }
258          }          }
# Line 233  sub downtime { Line 265  sub downtime {
265  #  #
266    
267  sub fmt_interval {  sub fmt_interval {
268          my $s = shift || 0;          my $int = shift || 0;
269          my $out = "";          my $out = "";
270    
271            my $s=$int;
272          my $d = int($s/(24*60*60));          my $d = int($s/(24*60*60));
273          $s = $s % (24*60*60);          $s = $s % (24*60*60);
274          my $h = int($s/(60*60));          my $h = int($s/(60*60));
# Line 245  sub fmt_interval { Line 278  sub fmt_interval {
278                    
279          $out .= $d."d " if ($d > 0);          $out .= $d."d " if ($d > 0);
280    
281          $out .= sprintf("%02d:%02d:%02d",$h,$m,$s);          if ($debug) {
282                    $out .= sprintf("%02d:%02d:%02d [%d]",$h,$m,$s, $int);
283            } else {
284                    $out .= sprintf("%02d:%02d:%02d",$h,$m,$s);
285            }
286    
287          return $out;          return $out;
288  }  }
# Line 256  sub fmt_interval { Line 293  sub fmt_interval {
293    
294  sub interval {  sub interval {
295          my $self = shift;          my $self = shift;
296          my $from = shift || die "need start time for interval";          my $from = shift || croak "need start time for interval";
297          my $to = shift || die "need end time for interval";          my $to = shift || croak "need end time for interval";
298    
299          print STDERR "from:\t$from\t",scalar gmtime($from),"\n" if ($debug);          print STDERR "from:\t$from\t",scalar localtime($from),"\n" if ($debug);
300          print STDERR "to:\t$to\t",scalar gmtime($to),"\n" if ($debug);          print STDERR "to:\t$to\t",scalar localtime($to),"\n" if ($debug);
301    
302          my $total = 0;          my $total = 0;
303    
304          # calc first day availability          # calc first day availability
305          print STDERR "t:\t$from\t",scalar gmtime($from),"\n" if ($debug);          print STDERR "t:\t$from\t",scalar localtime($from),"\n" if ($debug);
306          $total += $self->uptime($from);          $total += $self->uptime($from);
307    
308          print STDERR "total: $total (first)\n" if ($debug);          print STDERR "total: ",fmt_interval($total)," (first)\n" if ($debug);
309    
310          # add all whole days          # add all whole days
311    
312          my $sec_in_day = $self->sec_in_interval;          my $sec_in_day = $self->{sec_in_interval};
313          my $day = 86400;        # 24*60*60          my $day = 86400;        # 24*60*60
314    
315          my $loop_start_time = int($from/$day)*$day + $day;          my $loop_start_time = int($from/$day)*$day + $day;
316          my $loop_end_time = int($to/$day)*$day - $day;          my $loop_end_time = int($to/$day)*$day;
317    
318          print STDERR "loop (start - end): $loop_start_time - $loop_end_time\n" if ($debug);          print STDERR "loop (start - end): $loop_start_time - $loop_end_time\n" if ($debug);
319    
320          for (my $t = $loop_start_time; $t <= $loop_end_time; $t += $day) {          for (my $t = $loop_start_time; $t < $loop_end_time; $t += $day) {
321                  print STDERR "t:\t$t\t",scalar gmtime($t),"\n" if ($debug);                  print STDERR "t:\t$t\t",scalar localtime($t),"\n" if ($debug);
322                  $total += $sec_in_day if ($self->day_in_interval($t));                  $total += $sec_in_day if ($self->day_in_interval($t));
323                  print STDERR "total: $total (loop)\n" if ($debug);                  print STDERR "total: ",fmt_interval($total)," (loop)\n" if ($debug);
324          }          }
325    
326          # add rest of last day          # add rest of last day
327          print STDERR "t:\t$to\t",scalar gmtime($to),"\n" if ($debug);          print STDERR "t:\t$to\t",scalar localtime($to),"\n" if ($debug);
328    
329          $total -= $self->downtime($to);          if ($to > $self->_start($to)) {
330          print STDERR "total: $total (final)\n" if ($debug);                  if ($to <= $self->_end($to)) {
331                            $total = abs($total - $self->downtime($to));
332                    } elsif($self->day_in_interval($to) && $loop_start_time < $loop_end_time) {
333                            $total += $sec_in_day;
334                    }
335            } else {
336                    $total = abs($total - $self->downtime($to));
337            }
338            print STDERR "total: ",fmt_interval($total)," (final)\n" if ($debug);
339    
340          return $total;          return $total;
341  }  }
# Line 302  sub interval { Line 347  sub interval {
347  sub day_in_interval {  sub day_in_interval {
348          my $self = shift;          my $self = shift;
349    
350          my $time = shift || die "need timestamp to check if day is in interval";          my $time = shift || croak "need timestamp to check if day is in interval";
351    
352          my @lt = gmtime($time);          my @lt = localtime($time);
353          return $self->_dayOk($lt[6]);          return $self->_dayOk($lt[6]);
354  }  }
355    
# Line 312  sub day_in_interval { Line 357  sub day_in_interval {
357  # return seconds in defined interval  # return seconds in defined interval
358  #  #
359    
 sub sec_in_interval {  
         my $self = shift;  
   
         # over midnight?  
         if ($self->{start} > $self->{end}) {  
                 return(86400 - $self->{start} + $self->{end});  
         } else {  
                 return($self->{end} - $self->{start});  
         }  
 }  
360    
361  1;  1;
362  __END__  __END__
# Line 343  Time::Available - Perl extension to calc Line 378  Time::Available - Perl extension to calc
378    my $interval = new( start=>'07:00', stop=>'17:00',    my $interval = new( start=>'07:00', stop=>'17:00',
379          dayMask=> DAY_WEEKDAY );          dayMask=> DAY_WEEKDAY );
380    
381    # calculate current availability in seconds    # calculate current uptime availability from now in seconds
382    print $interval->uptime(localtime);    print $interval->uptime(localtime);
383    
384      # calculate maximum downtime in seconds from current moment
385      print $interval->downtime(localtime);
386    
387    # calculate availablity in seconds from interval of uptime    # calculate availablity in seconds from interval of uptime
388    print $interval->interval($utime1,$utime2);    print $interval->interval($utime1,$utime2);
389    
# Line 356  Time::Available - Perl extension to calc Line 394  Time::Available - Perl extension to calc
394  =head1 DESCRIPTION  =head1 DESCRIPTION
395    
396  Time::Available is used to calculate availability of some resource if start  Time::Available is used to calculate availability of some resource if start
397  end end time of availability is available. That availability is calculated  and end time of availability is supplied. Availability is calculated
398  relative to some interval which is defined when new instance of module is  relative to some interval which is defined when new instance of module is
399  created.  created.
400    
401  Start and end dates must be specified in 24-hour format. You can specify  Start and end dates must be specified in 24-hour format. You can specify
402  just hour, hour:minute or hour:minute:seconds format.  just hour, hour:minute or hour:minute:seconds format. Start and end time is
403    specified in your B<local time zone>. Timestamp, are specified in unix
404    utime, and module will take care of recalculating (using C<localtime> and
405    C<timelocal> when needed). There is one small canvat here: module is assuing
406    that time you are specifing is in same time zone in which your module is
407    running (that is from local system).
408    
409  The B<dayMask> parameter is constructed by OR'ing together one or more of  The B<dayMask> parameter is constructed by OR'ing together one or more of
410  the following dayMask constants:  the following dayMask constants:
# Line 400  Time::Available::DAY_EVERYDAY Line 443  Time::Available::DAY_EVERYDAY
443    
444  =back  =back
445    
446  FIXME  They should be self-explainatory.
447    
448  =head2 EXPORT  =head2 EXPORT
449    
# Line 429  Original version; based somewhat on Time Line 472  Original version; based somewhat on Time
472  =over 8  =over 8
473    
474  =item *  =item *
 Use croak and not die in module for better error handling  
   
 =item *  
475  Allow arbitary (array?) of holidays to be included.  Allow arbitary (array?) of holidays to be included.
476    
477  =back  =back
478    
479  =head1 SEE ALSO  =head1 SEE ALSO
480    
481  Time::Avail is CPAN module that started it all. However, it lacked  L<Time::Avail> is CPAN module that started it all. However, it lacked
482  calculating of availability of some interval and precision in seconds, so  calculating of availability of some interval and precision in seconds, so
483  this module was born.  this module was born. It also had some bugs in dayMask which where reported
484    to author, but his e-mail address bounced.
485    
486  More information about this module might be found on  More information about this module might be found on
487  http://www.rot13.org/~dpavlin/projects.html#cpan  http://www.rot13.org/~dpavlin/projects.html#cpan

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.11

  ViewVC Help
Powered by ViewVC 1.1.26