in reply to Dates - which Tuesday is it
DateTime is your best friend for this kind of logic. It is not straight forward, but DateTime has all the tools you need for working with day of week numbers and date math.
I don't know if it will help, but I had to do some day-of-week logic similar to what you describe when I wrote DateTimeX::Fiscal::Fiscal5253. I had to know what day of the week Jan 31 fell on then find the Sunday closest to it, whether it was the preceding Sunday, or the following Sunday, without regard to it being in January or February. Here is how I did it:
# The end day for a specified year is trivial to determine. In normal # accounting use, a fiscal year is named for the calendar year it ends + in, # not the year it begins. sub _end5253 { my $args = shift; my $dt = DateTime->last_day_of_month( year => $args->{year}, month => $args->{end_month}, time_zone => 'floating' ); my $eom_day = $dt->day; my $dt_dow = $dt->dow; if ( $dt_dow > $args->{end_dow} ) { $dt->subtract( days => $dt_dow - $args->{end_dow} ); } elsif ( $dt_dow < $args->{end_dow} ) { $dt->subtract( days => ($dt_dow + 7) - $args->{end_dow} ); } $dt->add( weeks => 1 ) if $args->{end_type} eq 'closest' && $eom_day - $dt->day > 3; return $dt; }
I know this is not exactly like your problem, but it should be similar enough in nature to demonstrate some of the tools DateTime provides for this kind of thing.
Update: added example for finding a preceding Friday
With specific regard to your question about determining if a given date is on a weekend you might try something like this:
#!/usr/bin/perl use v5.10; use strict; use warnings; use DateTime; my $dt1 = DateTime->new( year => 2013, month => 7, day => 5 ); my $dt2 = $dt1->clone->add( days => 15 ); if ( $dt2->dow > 5 ) { # July 20, 2013 happens to be a Saturday say "$dt2 falls on a weekend: " . $dt2->day_name; my $stepback = $dt2->dow - 5; # number of days back to Friday $dt2->subtract( days => $stepback ); say "The preceding Friday is $dt2"; } else { say "$dt2 is not on a weekend: " . $dt2->day_name; } exit; __END__
|
|---|