use strict; use warnings; use POSIX qw(strftime mktime); use Data::Dumper; sub ooh { my $start = shift; my $end = shift; my %wkwk = map {$_ => 1} (1..5); # Mon .. Fri my $i; my %mns = map{$_=>$i++}qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); # Bank holidays # We assume they all begin at 00:00:00 and encompas the entire day # POSIX::mktime(15, 28, 06, 27, 02, 206);' my @bh; while () { # read bank holiday file next unless /\d\d?\s+\w\w\w\s+\d{4}/; chomp; my ($day, $month, $year) = split; my $mnth = $mns{$month}; my $bh_start = POSIX::mktime(00, 00, 00, $day, $mnth, $year - 1900); next if $bh_start < time; # history push @bh, $bh_start; } @bh = sort @bh; return sub { my $epoch = shift; my ($s, $m, $h, $date, $mnth, $yr, $day) = +(localtime $epoch)[0 .. 6]; print $/; print scalar localtime $epoch; # Check if we are out of hours, and when next flip is due my $valid; my $ooh; if ($epoch > $bh[0]) { # its a new bank holiday shift @bh; # rip this page from the calendar $ooh = 1; print " Bank Holiday"; } if (not $ooh and $wkwk{$day}) { # not a bank hol, is a working day my $time = sprintf "%02d:%02d:%02d", $h,$m,$s; print " given: $time "; if ($time lt $start) { # not out of bed yet print "early doors "; ($h, $m, $s) = split /:/, $start; $valid = POSIX::mktime($s, $m, $h, $date, $mnth, $yr); return 1, $valid; } elsif ($time lt $end) { # came in, dreaming of home print "within working hours "; ($h, $m, $s) = split /:/, $end; $valid = POSIX::mktime($s, $m, $h, $date, $mnth, $yr); return 0, $valid; } else { print "g'night"; } } else { print " weekend" unless $ooh; } # find next working day my $add = 1; ++$add until $wkwk{($day + $add)%7}; print " Next working day is " .($day + $add)%7 . " "; # end of day, weekend or hols ($h, $m, $s) = split /:/, $start; $valid = POSIX::mktime($s, $m, $h, $date, $mnth, $yr); $valid+= $add * (24*60*60); return 1, $valid; } } # get an ooh tester my $ooh_check = ooh('08:15:00', '17:45:00'); # and run some tests print join " -> ", 'OOH', $ooh_check->(1382310123); print join " -> ", 'OOH', $ooh_check->(1359806999); print join " -> ", 'OOH', $ooh_check->(1360306452); print join " -> ", 'OOH', $ooh_check->(1381941000); print join " -> ", 'OOH', $ooh_check->(1360016452); print join " -> ", 'OOH', $ooh_check->(time); __DATA__ 01 Jan 2012 02 Feb 2013 03 Feb 2014 04 Aug 2013 21 Oct 2013