Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Calculating holidays

by htmanning (Friar)
on Jul 25, 2017 at 22:56 UTC ( [id://1196050]=perlquestion: print w/replies, xml ) Need Help??

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

Monks, I'm trying to calculate whether a given date is a major holiday, namely Thanksgiving. The string is in date format like this 2017-11-20. Using DateTime I can do things like tell the day of the week of the server, but how do I parse a date submitted in a string to figure out if it is the 4th Thursday of the month? I'm confused. I believe Thanksgiving is between the 22nd and 28th and the 4th Thursday of the month, but I don't know how to calculate that from a date. I can do something like this:
$thanks = "2017-11-24"; my ($thyear, $thmonth, $thday) = split(/-/,$thanks);
but I don't know how to figure out which Thursday it is.

Replies are listed 'Best First'.
Re: Calculating holidays
by choroba (Cardinal) on Jul 25, 2017 at 23:05 UTC
    See DateTime::Event::Holiday::US , and if you don't want to use it, check its source to see how it implements Thanksgiving.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Calculating holidays
by haukex (Archbishop) on Jul 26, 2017 at 09:34 UTC
    how do I parse a date

    Personally I like DateTime::Format::Strptime because it lets you define exactly the expected input format.

    figure out if it is the 4th Thursday of the month

    ( $datetime->dow==4 && $datetime->weekday_of_month==4 )

    Putting that together:

    use DateTime::Format::Strptime; my $strp = DateTime::Format::Strptime->new( pattern => '%Y-%m-%d', time_zone=>'UTC', on_error=>'croak' ); my $dt = $strp->parse_datetime('2017-11-23'); my $is_thanksgiving = $dt->month==11 && $dt->dow==4 && $dt->weekday_of_month==4;

    As for determining the date of Thanksgiving, I agree with choroba that the best thing to do is use an existing module. But just to demonstrate one way to do a calculation like that:

    sub thanksgiving { my $year = shift; my $dt = DateTime->new(year=>$year,month=>11,day=>1); $dt->add(days=>1) while $dt->dow!=4; $dt->add(weeks=>3); return $dt; }

    (Tested against data from Wikipedia for the years 2000 to 2399.)

      I'd probably write the thanksgiving function like this, because the keep-adding-one pattern gives me the jibblies.
      my $dt = DateTime->new(year=>$year, month=>11, day=>22); $dt->add(days=>(4 - $dt->dow())%7);

        Yes, that's a good point, the loop isn't very elegant. Personally I still like to anchor things at the beginning or end of the month, so I might write:

        my $dt = DateTime->new(year=>$year, month=>11); $dt->add( days=>(4-$dt->dow())%7, weeks=>3 );

        (But that's just getting nitpicky ;-) )

Re: Calculating holidays
by Anonymous Monk on Jul 26, 2017 at 01:38 UTC
    Thanksgiving day calculation for year $y, based on Zeller's congruence:
    my $k = $y % 100; my $j = int($y / 100); my $d = 28 - (5 + $k + ($k>>2) + ($j>>2) - 2*$j) % 7;
Re: Calculating holidays
by thanos1983 (Parson) on Jul 26, 2017 at 08:16 UTC

    Hello htmanning,

    Although the monks have provided you with knowledge, Just for fun I would like to point out one more module Date::Holidays::USFederal. Source code if you want to implement something similar Source (raw)

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
      Source code if you want to implement something similar Source (raw)

      That's a hard-coded list of dates from 1997 to 2025... not an implementation I'd recommend. Plus, they're US Federal Holidays and don't always fall on the same day as the actual holiday. For example, this year, New Year's Day was observed on Jaunary 2nd.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-16 10:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found