You either need a mktime that is time zone aware (POSIX::mktime seems to know about DST but not about time zones), or an UTC variant, e.g. Time::timegm. Of course, the logic of $today instead of time needs to be applied, anyway. (I tried it out, seems to work)
In the tests, the first date (from the future) kills too many holidays :-) (you should either sort the test data before the test, or create a new ooh() when time traveling)
Update: The easiest fix would have been (in the originally posted version):
my $today = POSIX::mktime(0,0,0,(localtime)[3..5]);
while (<DATA>) { # read bank holiday file
...
|