#!/usr/bin/perl use strict; use warnings; use POSIX qw(mktime); use Data::Dumper; use 5.014; sub ooh { my $start = shift; my $end = shift; my %wkwk = map {$_ => 1} @_; my @start = reverse split /:/, $start; # deliciously my @end = reverse split /:/, $end; # naughty 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; my $today = join ":", reverse +(localtime time)[3 .. 5]; while () { # read bank holiday file next unless /\d\d?\s+\w\w\w\s+\d{4}/; chomp; my ($day, $month, $year) = split; my $bh_start = join ":", $year-1900, $mns{$month}, $day; next if $bh_start lt $today; # 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]; # Check if we are out of hours, and when next flip is due my ($valid, $ooh); if ("$yr:$mnth:$date" eq $bh[0]) { # hooray! bank holiday shift @bh; # rip page from 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; if ($time lt $start) { # not out of bed yet print "Early doors "; $valid = POSIX::mktime(@start, $date, $mnth, $yr); $ooh = 1; } elsif ($time lt $end) { # came in, dreaming of home print "Working hours "; $valid = POSIX::mktime(@end, $date, $mnth, $yr); $ooh = 0; } else { print "G'night "; } } else { print "Weekend " unless $ooh; } unless ($valid) { # we did not establish our validity limit yet # we are at end of day, weekend or hols. Find next working day my $add = 1; ++$add until $wkwk{($day + $add)%7}; print "next working day is " .($day + $add)%7 . " "; $valid = POSIX::mktime(@start, $date, $mnth, $yr); $valid += $add * (24*60*60); # Daylight savings adjustment my $dst = $start[2] - +(localtime $valid)[2]; $valid += $dst * 60 * 60; $ooh = 1 } return $ooh, $valid; } } # get an ooh tester, work week mon..fri my $ooh_check = ooh('08:15:00', '17:45:00', 1..5); # and run some tests for (sort (time, 1382310123, 1359806999, 1360306452, 1381941000, 1360016452, 1382823512)) { my ($ooh, $valid) = $ooh_check->($_); say join " - ", scalar localtime $_, $ooh, scalar localtime $valid; } __DATA__ 02 Feb 2013 18 Oct 2013 21 Oct 2013 23 Oct 2013