{"id":4870,"date":"2009-11-07T12:51:15","date_gmt":"2009-11-07T17:51:15","guid":{"rendered":"http:\/\/scruss.com\/blog\/?p=4870"},"modified":"2009-11-07T12:51:15","modified_gmt":"2009-11-07T17:51:15","slug":"calculating-the-second-last-friday-of-the-month","status":"publish","type":"post","link":"https:\/\/scruss.com\/blog\/2009\/11\/07\/calculating-the-second-last-friday-of-the-month\/","title":{"rendered":"Calculating the second last Friday of the month"},"content":{"rendered":"<p>My boss, bless &#8216;im (no really, do; he&#8217;s a sound bloke, great guy to work for, and is just getting through some serious health problems), needs a monthly status report on the second last Friday of every month. I live by my calendar applications reminding me to do things, so I thought it&#8217;d be no problem getting Outlook to set up a reminder.<\/p>\n<p>No dice; it will only set up appointments on the 1st, 2nd, 3rd etc., starting from the beginning of the month. I did a web search, and really thought I&#8217;d found a <a href=\"http:\/\/infohost.nmt.edu\/tcc\/help\/org\/ical\/repeatappt.html\">solution<\/a> for iCal. It was not to be; this was for a Unix program called ICal; dratted case-insensitive search. Curiously, it appears that the ics spec <a href=\"http:\/\/www.shuchow.com\/vCalAddendum.html\">might support a second-from-last syntax<\/a>, but Outlook and iCal (and Google Calendar) can&#8217;t create them. Phooey.<\/p>\n<p>So I tried excel; and really thought I&#8217;d found the basis of an answer: <a href=\"http:\/\/excelexperts.com\/Excel-Tips-Last-Friday-in-the-month\">Last Friday of the month<\/a>. And indeed, most of their assumptions are right; the code<\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">DATE(year,month+1,1)-WEEKDAY(DATE(year,month+1,1),1)<\/pre>\n<p>really does give you the date of the last Saturday in the month. But you can&#8217;t assume that the day before the last Saturday is the last Friday &#8211; it is the second last, if the month ends on a Friday (April 2010 is a test case).<\/p>\n<p>So I tried the Swiss Army chainsaw of brute-force date calculation: Perl with <a href=\"http:\/\/search.cpan.org\/%7Estbey\/Date-Calc-6.3\/lib\/Date\/Calc.pod\">Date::Calc<\/a>. What I do here is create an array of every Friday in the month, then print the second last member; never known to fail:<\/p>\n<pre class=\"brush: perl; title: ; notranslate\" title=\"\">\r\n#!\/usr\/bin\/perl -w\r\n# second_last_friday.pl - show date of 2nd last friday\r\nuse strict;\r\nuse Date::Calc qw(Today\r\n  Nth_Weekday_of_Month_Year\r\n  Add_Delta_YMD);\r\nmy ( $new_year, $new_month ) = 0;\r\n\r\nmy ( $year, $month, $day ) = Today;\r\nforeach ( 1 .. 24 ) {\r\n    my @fridays = ();   # for every friday in this month\r\n    foreach my $week ( 1 .. 5 ) {\r\n        if (\r\n            ( $new_year, $new_month, $day ) =\r\n            Nth_Weekday_of_Month_Year(\r\n                $year, $month, 5, $week\r\n            )\r\n          )\r\n        {               # day of week 5 is Friday\r\n            push @fridays, $day;\r\n        }\r\n        else {\r\n            last;       # not a valid Friday\r\n        }\r\n    }\r\n    printf( &quot;%4d\/%02d\/%02d\\n&quot;,\r\n        $year, $month, $fridays&#x5B;-2] );\r\n    ( $year, $month, $day ) =\r\n      Add_Delta_YMD( $year, $month, 1, 0, 1, 0 )\r\n      ;                 # month++\r\n}\r\nexit;\r\n<\/pre>\n<p>and this gives<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n\r\n2009\/11\/20\r\n2009\/12\/18\r\n2010\/01\/22\r\n2010\/02\/19\r\n2010\/03\/19\r\n2010\/04\/23\r\n2010\/05\/21\r\n\r\n...\r\n\r\n<\/pre>\n<p>See, notice the tricksy 23 April 2010, which &#8211; considering thirty days hath April <em>et al<\/em> &#8211; ends on a Friday and threw that simple Excel calculation off.<\/p>\n<p>I&#8217;m disappointed that all these new applications like Outlook and iCal don&#8217;t seem to handle dates as elegantly as the old unix programs I used to use. <a href=\"http:\/\/pcal.sourceforge.net\/\">pcal<\/a>, in particular, could generate incredibly complex date formulae. I must dig around to solve this problem &#8211; and for now, actually have to remember to write that report on the second last Friday of this month &#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My boss, bless &#8216;im (no really, do; he&#8217;s a sound bloke, great guy to work for, and is just getting through some serious health problems), needs a monthly status report on the second last Friday of every month. I live by my calendar applications reminding me to do things, so I thought it&#8217;d be no [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[2],"tags":[175,255,187],"class_list":["post-4870","post","type-post","status-publish","format-standard","hentry","category-goatee-stroking-musing-or-something","tag-date","tag-excel","tag-perl"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pQNZZ-1gy","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/4870","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/comments?post=4870"}],"version-history":[{"count":13,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/4870\/revisions"}],"predecessor-version":[{"id":5050,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/4870\/revisions\/5050"}],"wp:attachment":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/media?parent=4870"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/categories?post=4870"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/tags?post=4870"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}