Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Dates - which Tuesday is it

by viffer (Beadle)
on Sep 17, 2013 at 00:12 UTC ( #1054360=perlquestion: print w/replies, xml ) Need Help??

viffer has asked for the wisdom of the Perl Monks concerning the following question:

Hi all-knowing. wonderful, helpful folks (I hope that's enough grovelling)?..

I have two ..tasks..I need to perform concerning date manipulation. I've searched high and low without success.

Firstly, I'm wondering if there's a perl module that enables me to find out whether a Tuesday is the 1st, 2nd, 3rd, 4th or 5th Tuesday in the month.

I need to run a process that does one thing on one Tuesday and an alternate thing on the next Tuesday, ad infinitum. I'm guessing the way to do it would be to find the odd/even numbered Tuesdays from epoch, but I'm buggered if I can work out how to do it.

The second issue I have is working out if a date 15 days from a given date is a weekend, i.e. if I'm given day 5 as input, I need to ascertain if day 20 is a weekend, so that I can run the job on the preceding Friday (18th or 19th).

I appreciate you prefer people to show the code they've written and the issues they've found, but quite honestly I've not been able to come up with anything worthwhile that isn't long winded or comes even close to working.

I really would appreciate any suggestions I could try

Thanks very much

Replies are listed 'Best First'.
Re: Dates - which Tuesday is it
by kcott (Bishop) on Sep 17, 2013 at 01:41 UTC

    G'day viffer,

    You can do all those date calculations with the built-in modules Time::Piece and Time::Seconds.

    Here are examples of the types of things you indicated. Do check the doco: there may be other ways to do these which more closely fit your requirements.

    $ perl -Mstrict -Mwarnings -E ' use Time::Piece; use Time::Seconds; my @ordinals = qw{1st 2nd 3rd 4th 5th}; my @even_odd = qw{even odd}; my $secs_per_week = 7 * 24 * 60 * 60; my $days_from_now = 15; my $now = localtime; say "Today is: ", $now->strftime; if ($now->fullday eq "Tuesday") { say "It is the $ordinals[$now->mday / 7] Tuesday of the month. +"; say "It is the ", int($now->epoch / $secs_per_week), "th Tuesday of the +epoch."; say "So it is an $even_odd[$now->epoch / $secs_per_week % 2] T +uesday."; } else { say "Not Tuesday: nothing to do."; } my $future = $now + ONE_DAY * $days_from_now; say "$days_from_now days from now will be: ", $future->strftime; say "That is ", $future->wdayname =~ /^(?:Sat|Sun)$/ ? "" : "not ", "a wee +kend."; ' Today is: Tue, 17 Sep 2013 11:38:22 EST It is the 3rd Tuesday of the month. It is the 2280th Tuesday of the epoch. So it is an even Tuesday. 15 days from now will be: Wed, 02 Oct 2013 11:38:22 EST That is not a weekend.

    -- Ken

Re: Dates - which Tuesday is it
by boftx (Deacon) on Sep 17, 2013 at 00:24 UTC

    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__
Re: Dates - which Tuesday is it
by McA (Priest) on Sep 17, 2013 at 00:29 UTC
      Yeah, I looked at "Week_of_Year", the problem is that I don't want to restart at week 1 the next year.

      Thanks though

Re: Dates - which Tuesday is it
by hdb (Monsignor) on Sep 17, 2013 at 07:12 UTC

    If $tue is the day of the month of your Tuesday, then int( ($tue-1) / 7 ) + 1; tells you, which one.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1054360]
Approved by Old_Gray_Bear
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2022-05-28 08:48 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (99 votes). Check out past polls.