have you sprung forward and not yet fallen back?
use Date::Calc qw( Nth_Weekday_of_Month_Year );
sub easterndaylight {
#this function expects
#YYYY-MM-DD HH:MM:SS with or without leading zeroes.
#it doesn't have very good error checking.
my $isodatetime;
$isodatetime = shift;
return undef unless $isodatetime;
my ($date,$time) = split(" ",$isodatetime);
my ($year,$mon,$day) = split("-",$date);
my ($hour,$min,$sec) = split(":",$time);
return 0 if ($mon < 4 || $mon > 10);
return 1 if ($mon > 4 && $mon < 10);
return undef unless ( ($mon == 4) or ($mon == 10) );
my ($dststarty,$dststartm,$dststartd);
my ($dstendy,$dstendm,$dstendd);
if($mon == 4) {
#first sunday of april:
($dststarty,$dststartm,$dststartd) =
Nth_Weekday_of_Month_Year($year,4,7,1);
if( $day < $dststartd ) {
return 0; #not yet
elsif ( $day > $dststartd ) {
return 1; #already sprung
} elsif ( $day == $dststartd ) {
return 0 if ($hour < 2);
return 1 if ($hour > 2);
# there should never be 02:* on a dst
# switch day, because you should go right
# from 01:59:59 to 03:00:00...
# but you never know.
return 1;
} else {
#uhh wtf?
return undef;
}
} elsif ( $mon == 10 ) {
# fall back on the last sunday of october
# try fifth sunday first, then try fourth
($dstendy,$dstendm,$dstendd) =
Nth_Weekday_of_Month_Year($year,10,7,4)
unless(($dstendy,$dstendm,$dstendd) =
Nth_Weekday_of_Month_Year($year,10,7,5));
if( $day < $dstendd ) {
#not there yet
return 1;
} elsif ( $day > $dstendd ) {
#already fell
return 0;
} elsif ( $day == $dstendd ) {
return 1 if $hour < 1;
return 0 if $hour > 1;
# the problem with DST
# is that on the last sunday
# in october, it's 01:00:00 through
# 01:59:59 twice because you fall back,
# so if you have the time/date from a machine
# that auto switches for dst or not dst and it
# doesn't include a timezone identifier,
# dates in that range are ambiguous.
# we're going to assume that it hasn't
# fallen yet. i hate dst.
return 1;
} else {
#wtf?
return undef;
}
} else {
return undef; #shouldn't make it here.
}
}