Last Friday of each month

From Rosetta Code
Task
Last Friday of each month
You are encouraged to solve this task according to the task description, using any language you may know.

Write a program or a script that returns the last Fridays of each month of a given year.

The year may be given through any simple input method in your language (command line, std in, etc.).

Example of an expected output:

./last_fridays 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28
Cf.

Ada

Uses GNAT. Applicable to any day of the week, cf. [[1]].

<lang Ada>with Ada.Text_IO, GNAT.Calendar.Time_IO, Ada.Command_Line,

 Ada.Calendar.Formatting, Ada.Calendar.Arithmetic;

procedure Last_Weekday_In_Month is

  procedure Put_Line(T: Ada.Calendar.Time) is
     use GNAT.Calendar.Time_IO;
  begin
     Ada.Text_IO.Put_Line(Image(Date => T, Picture => ISO_Date));
  end Put_Line;
  
  use Ada.Calendar, Ada.Calendar.Arithmetic;
  subtype Day_Name is Formatting.Day_Name; use type Formatting.Day_Name;
  
  T, Selected : Time;
  Weekday: Day_Name  := Day_Name'Value(Ada.Command_Line.Argument (1));
  Year : Year_Number := Integer'Value (Ada.Command_Line.Argument (2));
  

begin

  for Month in 1 .. 12 loop
     T := Time_Of (Year => Year, Month => Month, Day => 01);
     while Ada.Calendar.Month(T) = Month loop

if Formatting.Day_Of_Week (T) = Weekday then Selected := T; end if; T := T + Day_Count(1);

     end loop;
     Put_Line(Selected);
  end loop;

end Last_Weekday_In_Month;</lang>

Output:
>./last_weekday_in_month friday 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

AutoHotkey

<lang AHK>if 1 = ; no parameter passed { InputBox, 1, Last Fridays of year, Enter a year:, , , , , , , , %A_YYYY% If ErrorLevel ExitApp }

YYYY = %1% ; retrieve command line parameter Stmp = %YYYY%0101000000 count= 0

While count < 12 { FormatTime, ddd, %stmp%, ddd FormatTime, M, %stmp%, M If (ddd = "Fri"){ if (M-1 = count){ t := stmp stmp += 7, days } else res .= SubStr(t, 1, 4) "-" SubStr(t, 5, 2) "-" SubStr(t, 7, 2) "`n" ,count++ ,stmp := YYYY . SubStr("0" M, -1) . "01" } else stmp += 1, days } MsgBox % res</lang>

Output:

for 2012

2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

AutoIt

<lang AutoIt>

  1. include <Date.au3>

$iYear = InputBox('Last Friday in each month', 'Please input the year:')

_GetLastFridays($iYear)

Func _GetLastFridays($_iYear) Local $sResult = 'last fridays in ' & $_iYear & @LF, $iDay Local $aDaysInMonth[12] = [31,28,31,30,31,30,31,31,30,31,30,31] If _DateIsLeapYear($_iYear) Then $aDaysInMonth[1] = 29 For $i = 1 To 12 $iDay = $aDaysInMonth[$i-1] While 1 If _DateToDayOfWeekISO($_iYear, $i, $iDay) = 5 Then $sResult &= StringFormat('%4d-%02d-%02d', $_iYear, $i, $iDay) & @LF ExitLoop EndIf $iDay -= 1 WEnd Next ConsoleWrite($sResult) EndFunc  ;==>_GetFridays </lang>

Output:
last fridays in 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

--BugFix (talk) 13:27, 15 November 2013 (UTC)

AWK

<lang AWK>

  1. syntax: GAWK -f LAST_FRIDAY_OF_EACH_MONTH.AWK year
  2. converted from Fortran

BEGIN {

   split("31,28,31,30,31,30,31,31,30,31,30,31",daynum_array,",") # days per month in non leap year
   year = ARGV[1]
   if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
     daynum_array[2] = 29
   }
   y = year - 1
   k = 44 + y + int(y/4) + int(6*(y/100)) + int(y/400)
   for (m=1; m<=12; m++) {
     k += daynum_array[m]
     d = daynum_array[m] - (k%7)
     printf("%04d-%02d-%02d\n",year,m,d)
   }
   exit(0)

} </lang>

Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

C

Doesn't work with Julian calendar (then again, you probably don't need to plan your weekends for middle ages).

<lang c>#include <stdio.h>

  1. include <stdlib.h>

int main(int c, char *v[]) { int days[] = {31,29,31,30,31,30,31,31,30,31,30,31}; int m, y, w;

if (c < 2 || (y = atoi(v[1])) <= 1700) return 1;

	days[1] -= (y % 4) || (!(y % 100) && (y % 400));

w = y * 365 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + 6;

for(m = 0; m < 12; m++) { w = (w + days[m]) % 7; printf("%d-%02d-%d\n", y, m + 1, days[m] + (w < 5 ? -2 : 5) - w); }

return 0; }</lang>

C#

<lang csharp>using System; using System.Collections.Generic; using System.Globalization; using System.Linq;

namespace RosettaCode.LastFridaysOfYear {

   internal static class Program
   {
       private static IEnumerable<DateTime> LastFridaysOfYear(int year)
       {
           for (var month = 1; month <= 12; month++)
           {
               var date = new DateTime(year, month, 1).AddMonths(1).AddDays(-1);
               while (date.DayOfWeek != DayOfWeek.Friday)
               {
                   date = date.AddDays(-1);
               }
               yield return date;
           }
       }
       private static void Main(string[] arguments)
       {
           int year;
           var argument = arguments.FirstOrDefault();
           if (string.IsNullOrEmpty(argument) || !int.TryParse(argument, out year))
           {
               year = DateTime.Today.Year;
           }
           foreach (var date in LastFridaysOfYear(year))
           {
               Console.WriteLine(date.ToString("d", CultureInfo.InvariantCulture));
           }
       }
   }

}</lang>

Output:
01/27/2012
02/24/2012
03/30/2012
04/27/2012
05/25/2012
06/29/2012
07/27/2012
08/31/2012
09/28/2012
10/26/2012
11/30/2012
12/28/2012

C++

Library: Boost

called with ./last_fridays 2012 <lang cpp>#include <boost/date_time/gregorian/gregorian.hpp>

  1. include <iostream>
  2. include <cstdlib>

int main( int argc , char* argv[ ] ) {

  using namespace boost::gregorian ;
  greg_month months[ ] = { Jan , Feb , Mar , Apr , May , Jun , Jul ,
     Aug , Sep , Oct , Nov , Dec } ;
  greg_year gy = atoi( argv[ 1 ] ) ;
  for ( int i = 0 ; i < 12 ; i++ ) {
     last_day_of_the_week_in_month lwdm ( Friday , months[ i ] ) ;
     date d = lwdm.get_date( gy ) ;
     std::cout << d << std::endl ;
  }
  return 0 ;

}</lang>

Output:
2012-Jan-27
2012-Feb-24
2012-Mar-30
2012-Apr-27
2012-May-25
2012-Jun-29
2012-Jul-27
2012-Aug-31
2012-Sep-28
2012-Oct-26
2012-Nov-30
2012-Dec-28

Clojure

Library: clj-time

<lang clojure>(use '[clj-time.core :only [last-day-of-the-month day-of-week minus days]]

    '[clj-time.format :only [unparse formatters]])

(defn last-fridays [year]

 (let [last-days (map #(last-day-of-the-month year %) (range 1 13 1)) 
       dow (map day-of-week last-days) 
       relation (zipmap last-days dow)] 
   (map #(minus (key %) (days (mod (+ (val %) 2) 7))) relation)))

(defn last-fridays-formatted [year]

 (sort (map #(unparse (formatters :year-month-day) %) (last-fridays year))))</lang>
Output:
user=> (pprint (last-fridays-formatted 2012))
("2012-01-27"
 "2012-02-24"
 "2012-03-30"
 "2012-04-27"
 "2012-05-25"
 "2012-06-29"
 "2012-07-27"
 "2012-08-31"
 "2012-09-28"
 "2012-10-26"
 "2012-11-30"
 "2012-12-28")

CoffeeScript

<lang coffeescript> last_friday_of_month = (year, month) ->

 # month is 1-based, JS API is 0-based, then we use
 # non-positive indexes to work backward relative to the
 # first day of the next month
 i = 0
 while true
   last_day = new Date(year, month, i) 
   if last_day.getDay() == 5
     return last_day.toDateString()
   i -= 1

print_last_fridays_of_month = (year) ->

 for month in [1..12]
   console.log last_friday_of_month year, month

do ->

 year = parseInt process.argv[2]
 print_last_fridays_of_month year

</lang>

Output:

<lang> > coffee last_friday.coffee 2012 Fri Jan 27 2012 Fri Feb 24 2012 Fri Mar 30 2012 Fri Apr 27 2012 Fri May 25 2012 Fri Jun 29 2012 Fri Jul 27 2012 Fri Aug 31 2012 Fri Sep 28 2012 Fri Oct 26 2012 Fri Nov 30 2012 Fri Dec 28 2012 </lang>

Common Lisp

Works with: CLISP

The command-line argument processing is the only CLISP-specific code.

<lang lisp>(defun friday-before (year month day)

(let* 
 ((timestamp (encode-universal-time 0 0 12 day month year))
  (weekday (nth 6 (multiple-value-list (decode-universal-time timestamp))))
  (fri (- timestamp (* (+ (mod (+ weekday 2) 7) 1) 86400))))
   (multiple-value-bind (_ _ _ d m y) (decode-universal-time fri)
    (list y m d))))
   

(defun last-fridays (year)

 (append (loop for month from 2 to 12 collecting (friday-before year month 1))
         (list (friday-before (1+ year) 1 1))))

(let* ((year (read-from-string (car *args*))))

 (format t "~{~{~a-~2,'0d-~2,'0d~}~%~}" (last-fridays year)))</lang>

Sample run for the year 2015:

Output:
2015-01-30
2015-02-27
2015-03-27
2015-04-24
2015-05-29
2015-06-26
2015-07-31
2015-08-28
2015-09-25
2015-10-30
2015-11-27
2015-12-25

D

<lang d>import std.stdio, std.datetime, std.traits;

void lastFridays(in uint year) {

   auto date = Date(year, 1, 1);
   foreach (_; [EnumMembers!Month]) {
       date.day(date.daysInMonth);
       date.roll!"days"(-(date.dayOfWeek + 2) % 7);
       writeln(date);
       date.add!"months"(1, AllowDayOverflow.no);
   }

}

void main() {

   lastFridays(2012);

}</lang>

2012-Jan-27
2012-Feb-24
2012-Mar-30
2012-Apr-27
2012-May-25
2012-Jun-29
2012-Jul-27
2012-Aug-31
2012-Sep-28
2012-Oct-26
2012-Nov-30
2012-Dec-28

Erlang

<lang Erlang> -module( last_date_each_month ).

-export( [monday/1, tuesday/1, wednesday/1, thursday/1, friday/1, saturday/1, sunday/1] ).

monday( Year ) -> last( Year, 1 ). tuesday( Year ) -> last( Year, 2 ). wednesday( Year ) -> last( Year, 3 ). thursday( Year ) -> last( Year, 4 ). friday( Year ) -> last( Year, 5 ). saturday( Year ) -> last( Year, 6 ). sunday( Year ) -> last( Year, 7 ).


last( Year, Week_day ) ->

   Months = lists:seq( 1, 12 ),
   Months_days = [{X, Y} || X <- Months, Y <- lists:seq(calendar:last_day_of_the_month(Year, X), calendar:last_day_of_the_month(Year, X) - 7, -1), calendar:valid_date(Year, X, Y), calendar:day_of_the_week(Year, X, Y) =:= Week_day],
   [{Year, X, proplists:get_value(X, Months_days)} || X <- Months].

</lang>

Output:
32> [io:fwrite("~B-~2.10.0B-~B~n", [Y,M,D]) || {Y,M,D} <- last_date_each_month:friday(2012)].
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Fortran

Algorithm: compute day of week for last day of month, then subtract just enough to get to the preceding friday. Do this for each month. To simplify computations further, we only need to compute day of week of january 1st (the others are found by adding month lengths). Since day of week need only be known modulo 7, we do not compute modulo at all except once when subtracting. <lang fortran>program fridays

  implicit none
  integer :: days(1:12) = (/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
  integer :: year, k, y, m
  read *, year
  if (mod(year, 400) == 0 .or. (mod(year, 4) == 0 .and. mod(year, 100) /= 0)) days(2) = 29
  y = year - 1
  k = 44 + y + y/4 + 6*(y/100) + y/400
  do m = 1, 12
     k = k + days(m)
     print "(I4,A1,I2.2,A1,I2)", year, '-', m, '-', days(m) - mod(k, 7)
  end do

end program </lang>

FreeBASIC

<lang FreeBasic>' version 23-06-2015 ' compile with: fbc -s console

  1. Define FALSE 0
  2. Define TRUE Not FALSE

Function leapyear(Year_ As Integer) As Integer

   ' from the leapyeat entry
   If (Year_ Mod 4) <> 0 Then Return FALSE
   If (Year_ Mod 100) = 0 AndAlso (Year_ Mod 400) <> 0 Then Return FALSE
   Return TRUE

End Function

Function wd(m As Integer, d As Integer, y As Integer) As Integer

   ' Zellerish
   ' 0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday
   ' 4 = Thursday, 5 = Friday, 6 = Saturday
   If m < 3 Then        ' If m = 1 Or m = 2 Then
       m += 12
       y -= 1
   End If
   Return (y + (y \ 4) - (y \ 100) + (y \ 400) + d + ((153 * m + 8) \ 5)) Mod 7

End Function

' ------=< MAIN >=------

Type month_days

   m_name As String
   days As UByte

End Type

Dim As month_days arr(1 To 12) Data "January", 31, "February", 28, "March", 31, "April", 30 Data "May", 31, "June", 30, "July", 31, "August", 31 Data "September", 30, "October", 31, "November", 30, "December", 31

Dim As Integer yr, d, i, x Dim As String keypress

For i = 1 To 12

   With arr(i)
       Read .m_name
       Read .days
   End With

Next

Do

   Do
       Print "For what year do you want to find the last Friday of the month"
       Input "any number below 1800 stops program, year in YYYY format";yr
       ' empty input also stops
       If yr < 1800 Then
           End
       Else
           Exit Do
       EndIf
   Loop
   Print : Print
   Print "Last Friday of the month for"; yr
   For i = 1 To 12
       d = arr(i).days
       If i = 2 AndAlso leapyear(yr) = TRUE Then d = d + 1
       x = wd(i, d, yr)
       If x <> 5 Then d = d - IIf(x > 5, x - 5, x + 2)
       Print d; " "; arr(i).m_name
   Next
   ' empty key buffer
   While InKey <> "" : keypress = InKey : Wend
   Print : Print
   Print "Find last Friday for a other year [Y|y], anything else stops"
   keypress =""
   While keypress = "" : keypress = InKey : Wend
   If LCase(keypress) <> "y" Then Exit Do
   Print : Print

Loop End</lang>

Output:
For what year do you want to find the last Friday of the month
any number below 1800 stops program, year in YYYY format? 2015

Last Friday of the month for 2015
 30 January
 27 February
 27 March
 24 April
 29 May
 26 June
 31 July
 28 August
 25 September
 30 October
 27 November
 25 December

Go

<lang go>package main

import ( "fmt" "os" "strconv" "time" )

func main() { y := time.Now().Year() if len(os.Args) == 2 { if i, err := strconv.Atoi(os.Args[1]); err == nil { y = i } } for m := time.January; m <= time.December; m++ { d := time.Date(y, m+1, 1, 0, 0, 0, 0, time.UTC).Add(-24 * time.Hour) d = d.Add(-time.Duration((d.Weekday()+7-time.Friday)%7) * 24 * time.Hour) fmt.Println(d.Format("2006-01-02")) } }</lang>

Output:
> ./fridays 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Groovy

Solution: Same as Find last Sunday of each month

Test: <lang groovy>def ymd = { it.format('yyyy-MM-dd') } def lastFridays = lastWeekDays.curry(Day.Fri) lastFridays(args[0] as int).each { println (ymd(it)) }</lang>

Execution (Cygwin on Windows 7):

[2273] groovy lastFridays.groovy 2012
Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Haskell

<lang Haskell>import Data.Time.Calendar import Data.Time.Calendar.WeekDate

findFriday date = head $ filter isFriday $ map toDate [-6 .. 0]

 where
   toDate ago = addDays ago date
   isFriday theDate = let (_ , _ , day) = toWeekDate theDate
                      in day == 5 

fridayDates year = map (showGregorian . findFriday) lastDaysInMonth

 where
   lastDaysInMonth = map findLastDay [1 .. 12]
   findLastDay month = fromGregorian year month (gregorianMonthLength year month)

main = do

 putStrLn "Please enter a year!"
 year <- getLine
 mapM_ putStrLn $ fridayDates (read year)</lang>
Output:
Please enter a year!
2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Icon and Unicon

This will write the last fridays for every year given as an argument. There is no error checking on the year. <lang Icon>procedure main(A) every write(lastfridays(!A)) end

procedure lastfridays(year) every m := 1 to 12 do {

  d := case m of {
     2        : if IsLeapYear(year) then 29 else 28
     4|6|9|11 : 30
     default  : 31
     }                          # last day of month
      
  z := 0  
  j := julian(m,d,year) + 1     # first day of next month
  until (j-:=1)%7 = 4 do z -:=1 # backup to last friday=4
  suspend sprintf("%d-%d-%d",year,m,d+z)
  }

end

link datetime, printf</lang>

printf.icn provides formatting datetime.icn provides julian and IsLeapYear

Output:
last_fridays.exe 2012
2012-1-27
2012-2-24
2012-3-30
2012-4-27
2012-5-25
2012-6-29
2012-7-27
2012-8-31
2012-9-28
2012-10-26
2012-11-30
2012-12-28

J

<lang j>require 'dates' last_fridays=: 12 {. [: ({:/.~ }:"1)@(#~ 5 = weekday)@todate (i.366) + todayno@,&1 1</lang>

In other words, start from January 1 of the given year, and count forward for 366 days, keeping the Fridays. Then pick the last remaining day within each represented month (which will be a Friday because we only kept the Fridays). Then pick the first 12 (since on a non-leap year which ends on a Thursday we would get an extra Friday).

Example use:

<lang j> last_fridays 2012 2012 1 27 2012 2 24 2012 3 30 2012 4 27 2012 5 25 2012 6 29 2012 7 27 2012 8 31 2012 9 28 2012 10 26 2012 11 30 2012 12 28</lang>

Java

Works with: Java version 1.5+

<lang java5>import java.text.*; import java.util.*;

public class LastFridays {

   public static void main(String[] args) throws Exception {
       int year = Integer.parseInt(args[0]);
       GregorianCalendar c = new GregorianCalendar(year, 0, 1);
       for (String mon : new DateFormatSymbols(Locale.US).getShortMonths()) {
           if (!mon.isEmpty()) {
               int totalDaysOfMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH);
               c.set(Calendar.DAY_OF_MONTH, totalDaysOfMonth);
               int daysToRollBack = (c.get(Calendar.DAY_OF_WEEK) + 1) % 7;
               int day = totalDaysOfMonth - daysToRollBack;
               c.set(Calendar.DAY_OF_MONTH, day);
               System.out.printf("%d %s %d\n", year, mon, day);
               c.set(year, c.get(Calendar.MONTH) + 1, 1);
           }
       }
   }

}</lang>

Output:

(for java LastFridays 2012)

2012 Jan 27
2012 Feb 24
2012 Mar 30
2012 Apr 27
2012 May 25
2012 Jun 29
2012 Jul 27
2012 Aug 31
2012 Sep 28
2012 Oct 26
2012 Nov 30
2012 Dec 28


jq

Works with: jq version 1.4

Foundations <lang jq># In case your jq does not have "until" defined:

def until(cond; next):

 def _until:
   if cond then . else (next|_until) end;
 _until;
  1. Zeller's Congruence is from Day_of_the_week#jq
  1. Use Zeller's Congruence to determine the day of the week, given
  2. year, month and day as integers in the conventional way.
  3. If iso == "iso" or "ISO", then emit an integer in 1 -- 7 where
  4. 1 represents Monday, 2 Tuesday, etc;
  5. otherwise emit 0 for Saturday, 1 for Sunday, etc.

def day_of_week(year; month; day; iso):

 if month == 1 or month == 2 then
   [year - 1, month + 12, day]
 else
   [year, month, day]
 end
 | .[2] + (13*(.[1] + 1)/5|floor) 
   +  (.[0]%100)       + ((.[0]%100)/4|floor)
   +  (.[0]/400|floor) - 2*(.[0]/100|floor)
 | if iso == "iso" or iso == "ISO" then 1 + ((. + 5) % 7)
   else . % 7
   end ;</lang>

findLastFridays <lang jq># year and month are numbered conventionally def findLastFriday(year; month):

 def isLeapYear:
   year%4 == 0 and ( year%100!=0 or year%400==0 ) ;
 def days:
   if month == 2 then (if isLeapYear then 29 else 28 end)
   else [31, 28, 31,30,31,30,31,31,30,31,30,31][month-1]
   end;
 year as $year
 | month as $month
 | days
 | until( day_of_week($year; $month; .; null) == 6 ; .-1);
  1. input: year

def findLastFridays:

 def months:
   ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
 . as $year
 | "YEAR: \(.)",
   (range(0;12) | "\(months[.]) \(findLastFriday($year; .+1))") ;

$year|tonumber|findLastFridays</lang>

Output:

<lang sh>$ jq --arg year 2012 -n -r -f findLastFridays.jq YEAR: 2012 January 27 February 24 March 30 April 27 May 25 June 29 July 27 August 31 September 28 October 26 November 30 December 28</lang>

Julia

<lang Julia> isdefined(:Date) || using Dates

const wday = Dates.Fri const lo = 1 const hi = 12

print("\nThis script will print the last ", Dates.dayname(wday)) println("s of each month of the year given.") println("(Leave input empty to quit.)")

while true

   print("\nYear> ")
   y = chomp(readline())
   0 < length(y) || break
   y = try
       parseint(y)
   catch
       println("Sorry, but \"", y, "\" does not compute as a year.")
       continue
   end
   println()
   for m in Date(y, lo):Month(1):Date(y, hi)
       println("    ", tolast(m, wday))
   end

end </lang>

This code uses the Dates module, which is being incorporated into Julian's standard library with the current development version (0.4). I've used isdefined to make this code good for the current stable version (0.3) as well as for future releases. If Dates is not installed on your instance of Julian try Pkg.add("Dates") from the REPL.

Output:
This script will print the last Fridays of each month of the year given.
(Leave input empty to quit.)

Year> 2012

    2012-01-27
    2012-02-24
    2012-03-30
    2012-04-27
    2012-05-25
    2012-06-29
    2012-07-27
    2012-08-31
    2012-09-28
    2012-10-26
    2012-11-30
    2012-12-28

Year> this year 
Sorry, but "this year" does not compute as a year.

Year> 

Lasso

<lang Lasso>define isLeapYear(y::integer) => { #y % 400 == 0 ? return true #y % 100 == 0 ? return false #y % 4 == 0 ? return true return false } define fridays(y::integer) => { local(out = array) loop(12) => { local(last = 28) loop_count == 2 && isLeapYear(#y) ? #last = 29 array(4,6,9,11) >> loop_count ? #last == 30 #last == 28 && loop_count != 2 ? #last = 31 local(start = date(-year=#y,-month=loop_count,-day=#last)) while(#start->dayofweek != 6) => { #start->subtract(-day=1) } #out->insert(#start) } return #out } with f in fridays(2012) do => {^ #f->format('%Q') + '\r' ^}</lang>

Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

<lang logo>; Determine if a Gregorian calendar year is leap to leap? :year

 output (and 
   equal? 0 modulo :year 4
   not member? modulo :year 400 [100 200 300]
 )

end

Convert Gregorian calendar date to a simple day count from
RD 1 = January 1, 1 CE

to day_number :year :month :day

 local "elapsed make "elapsed difference :year 1
 output (sum  product 365 :elapsed
             int quotient :elapsed 4
             minus int quotient :elapsed 100
             int quotient :elapsed 400
             int quotient difference product 367 :month 362 12
             ifelse lessequal? :month 2 0 ifelse leap? :year -1 -2
             :day)

end

Find the day of the week from a day number, 0 = Sunday through 6 = Saturday

to day_of_week :day_number

 output modulo :day_number 7

end

Find the date of the last Friday of a given month

to last_friday :year :month

 local "zero make "zero day_number :year :month 0
 local "last make "last day_number :year sum 1 :month 0
 local "wday make "wday day_of_week :last
 local "friday make "friday sum :last remainder difference -2 :wday 7
 output difference :friday :zero

end

local "year make "year ifelse empty? :command.line 2012 :command.line

repeat 12 [

 local "month make "month #
 local "day make "day last_friday :year :month
 if (less? :month 10) [make "month word "0 :month]
 print reduce [(word ?1 "- ?2)] (list :year :month :day)

] bye</lang>

Output:
$  logo last_fridays.lg - 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Mathematica

<lang Mathematica>FridaysOfYear[Y_] :=

NestWhile[(DaysPlus[#, - 1]) &, #, (DateString[#, "DayName"] != "Friday") &] & /@ 
 Most@Reverse@NestList [DaysPlus[# /. {x_, y_, X_} -> {x, y, 1}, - 1] &, {Y + 1, 1, 1}, 12]

Column@FridaysOfYear[2012]</lang>

Output:
{2012,1,27}
{2012,2,24}
{2012,3,30}
{2012,4,27}
{2012,5,25}
{2012,6,29}
{2012,7,27}
{2012,8,31}
{2012,9,28}
{2012,10,26}
{2012,11,30}
{2012,12,28}

MATLAB / Octave

<lang Matlab> function t = last_fridays_of_year(y)

 t1 = datenum([y,1,1,0,0,0]);
 t2 = datenum([y,12,31,0,0,0]);
 t  = datevec(t1:t2);
 t  = t(strmatch('Friday', datestr(t,'dddd')), :);     % find all Fridays
 t  = t([find(diff(t(:,2)) > 0); end], :);     % find Fridays before change of month
 end; 
 datestr(last_fridays_of_year(2012),'yyyy-mm-dd')		

</lang>

Output:
  ans =
  2012-01-27
  2012-02-24
  2012-03-30
  2012-04-27
  2012-05-25
  2012-06-29
  2012-07-27
  2012-08-31
  2012-09-28
  2012-10-26
  2012-11-30
  2012-12-28

Maxima

<lang maxima>weekday(year, month, day) := block([m: month, y: year, k],

  if m < 3 then (m: m + 12,  y: y - 1), 
  k: 1 + remainder(day + quotient((m + 1)*26,  10) + y + quotient(y,  4)
       + 6*quotient(y,  100) + quotient(y,  400) + 5,  7), 
  ['monday,  'tuesday,  'wednesday,  'thurdsday,  'friday,  'saturday,  'sunday][k]

)$

leapyearp(year) := is(mod(year, 4) = 0 and (mod(year, 100) # 0 or mod(year, 400) = 0))$


lastfridays(year) := block(

  [m: [31,  if leapyearp(year) then 29 else 28,  31,  30,  31,  30,  31,  31,  30,  31,  30,  31],  v: [ ]], 
  for month thru 12 do v: endcons(sconcat(year,  "-",  month,  "-", 
     lmax(sublist(makelist(i,  i,  1,  m[month]),  lambda([day],  weekday(year,  month,  day) = 'friday)))),  v), 
  v

)$

lastfridays(2012); ["2012-1-27", "2012-2-24", "2012-3-30", "2012-4-27", "2012-5-25", "2012-6-29", "2012-7-27","2012-8-31", "2012-9-28", "2012-10-26", "2012-11-30", "2012-12-28"]</lang>

NetRexx

Translation of: Java
Translation of: C

Implements the algorithms from both the Java and C implementations. <lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols nobinary

import java.text.

runSample(arg) return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method lastFridayByLib(year) public static

 cal = GregorianCalendar(year, 0, 1)
 loop mon over DateFormatSymbols().getShortMonths()
   if \mon.isEmpty() then do
     totalDaysOfMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH)
     cal.set(Calendar.DAY_OF_MONTH, totalDaysOfMonth)
     daysToRollBack = (cal.get(Calendar.DAY_OF_WEEK) + 1) // 7
     day = totalDaysOfMonth - daysToRollBack
     cal.set(Calendar.DAY_OF_MONTH, day)
     say year.right(4, 0) mon day.right(2, 0)
     cal.set(year, cal.get(Calendar.MONTH) + 1, 1)
     end
   end mon
 return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method lastFridayCalc(year) public static binary signals BadArgumentException

 if year <= 1700 then do
   signal BadArgumentException(year 'is out of range')
   end
 wk  = int
 mth = int
 yr  = int year
 days = [int 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]  -- days in month
 days[1] = days[1] - ((yr // 4) | \(yr // 100) & (yr // 400)) -- adjust for leap year
 wk = yr * 365 + (yr - 1) % 4 - (yr - 1) % 100 + (yr - 1) % 400 + 6 -- week number
 loop mth = 0 to 11
   wk = (wk + days[mth]) // 7
   wx = int
   if wk < 5 then wx = -2
             else wx = 5
   yy = Rexx(yr)
   mm = Rexx(mth + 1)
   dd = Rexx(days[mth] + wx - wk)
   say yy.right(4, 0)'-'mm.right(2, 0)'-'dd.right(2, 0)
   end mth
 return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method runSample(arg) private static

 do
   parse arg year .
   if year =  | year = '.' then year = 2012
   dlm = '-'
   dlm = dlm.left(60, dlm)
   say
   say 'Using Java calendar libraries'
   say dlm
   lastFridayByLib(year)
   say
   say 'Calculated'
   say dlm
   lastFridayCalc(year)
 catch ex = Exception
   ex.printStackTrace
 end
 return

</lang>

Output:
Using Java calendar libraries
------------------------------------------------------------
2012 Jan 27
2012 Feb 24
2012 Mar 30
2012 Apr 27
2012 May 25
2012 Jun 29
2012 Jul 27
2012 Aug 31
2012 Sep 28
2012 Oct 26
2012 Nov 30
2012 Dec 28

Calculated
------------------------------------------------------------
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Nim

<lang nim>import times, os, strutils

var timeinfo = getLocalTime getTime() timeinfo.year = paramStr(1).parseInt for month in mJan .. mDec:

 timeinfo.month = month
 for day in countdown(31, 1):
   timeinfo.monthday = day
   let t = getLocalTime(timeInfoToTime timeinfo)
   if t.month == month and t.weekday == dFri:
     echo t.format "yyyy-MM-dd"
     break</lang>

Sample usage:

./lastfriday 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

OCaml

Using the module Unix from the standard OCaml library:

<lang ocaml>#load "unix.cma" open Unix

let usage() =

 Printf.eprintf "%s <year>\n" Sys.argv.(0);
 exit 1

let print_date t =

 Printf.printf "%d-%02d-%02d\n" (t.tm_year + 1900) (t.tm_mon + 1) t.tm_mday

let is_date_ok tm t =

 (tm.tm_year = t.tm_year &&
  tm.tm_mon  = t.tm_mon  &&
  tm.tm_mday = t.tm_mday)

let () =

 let _year =
   try int_of_string Sys.argv.(1)
   with _ -> usage()
 in
 let year = _year - 1900 in
 let fridays = Array.make 12 (Unix.gmtime 0.0) in
 for month = 0 to 11 do
   for day_of_month = 1 to 31 do
     let tm = { (Unix.gmtime 0.0) with 
       tm_year = year;
       tm_mon = month;
       tm_mday = day_of_month;
     } in
     let _, t = Unix.mktime tm in
     if is_date_ok tm t  (* check for months that have less than 31 days *)
     && t.tm_wday = 5  (* is a friday *)
     then fridays.(month) <- t
   done;
 done;
 Array.iter print_date fridays</lang>
Output:
$ ocaml last_fridays.ml 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

With a dedicated library

<lang ocaml>open CalendarLib

let usage() =

 Printf.eprintf "%s <year>\n" Sys.argv.(0);
 exit 1

let print_date (year, month, day) =

 Printf.printf "%d-%02d-%02d\n" year month day

let () =

 let year =
   try int_of_string Sys.argv.(1)
   with _ -> usage()
 in
 let fridays = ref [] in
 for month = 1 to 12 do
   let num_days = Date.days_in_month (Date.make_year_month year month) in
   let rec aux day =
     if Date.day_of_week (Date.make year month day) = Date.Fri
     then fridays := (year, month, day) :: !fridays
     else aux (pred day)
   in
   aux num_days
 done;
 List.iter print_date (List.rev !fridays)</lang>

Run this script with the command:

ocaml unix.cma str.cma -I +calendar calendarLib.cma last_fridays.ml 2012


Oforth

<lang Oforth>func: lastFridays(y) { | m |

  Date.JANUARY Date.DECEMBER for: m [
     Date newDate(y, m, Date.DaysInMonth(y, m))
     while(dup dayOfWeek Date.FRIDAY <>) [ addDays(-1) ]
     println
     ]

}</lang>

Output:
2012-01-27 00:00:00,000
2012-02-24 00:00:00,000
2012-03-30 00:00:00,000
2012-04-27 00:00:00,000
2012-05-25 00:00:00,000
2012-06-29 00:00:00,000
2012-07-27 00:00:00,000
2012-08-31 00:00:00,000
2012-09-28 00:00:00,000
2012-10-26 00:00:00,000
2012-11-30 00:00:00,000
2012-12-28 00:00:00,000

Perl

<lang Perl>#!/usr/bin/perl -w use strict ; use DateTime ; use feature qw( say ) ;

foreach my $month ( 1..12 ) {

  my $dt = DateTime->last_day_of_month( year => $ARGV[ 0 ] , month => $month ) ;
  while ( $dt->day_of_week != 5 ) {
     $dt->subtract( days => 1 ) ;
  }
  say $dt->ymd ;

}</lang>

Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Perl 6

<lang perl6>sub MAIN (Int $year = Date.today.year) {

   my @fri;
   for Date.new("$year-01-01") .. Date.new("$year-12-31") {
       @fri[.month] = .Str if .day-of-week == 5;
   }
   .say for @fri[1..12];

}</lang>

Example:

$ ./lastfri 2038
2038-01-29
2038-02-26
2038-03-26
2038-04-30
2038-05-28
2038-06-25
2038-07-30
2038-08-27
2038-09-24
2038-10-29
2038-11-26
2038-12-31

A solution without a result array to store things in:

<lang perl6>sub MAIN (Int $year = Date.today.year) {

   say ~.value.reverse.first: *.day-of-week == 5
       for classify *.month, Date.new("$year-01-01") .. Date.new("$year-12-31");

}</lang>

Here, classify sorts the dates into one bin per month (but preserves the order in each bin). We then take the list inside each bin (.value) and find the last (.reverse.first) date which is a Friday.

Another variation where the data flow can be read left to right using feed operators:

<lang perl6>sub MAIN (Int $year = Date.today.year) {

   .say for Date.new("$year-01-01") .. Date.new("$year-12-31") ==> classify *.month ==>
            map *.value.reverse.first: *.day-of-week == 5

}</lang>

PHP

PHP is generally used for web apps, so I am not implementing the command-line component of this task.

<lang PHP><?php function last_friday_of_month($year, $month) {

 $day = 0;
 while(True) {
   $last_day = mktime(0, 0, 0, $month+1, $day, $year); 
   if (date("w", $last_day) == 5) {
     return date("Y-m-d", $last_day);
   }
   $day -= 1;
 }

}

function print_last_fridays_of_month($year) {

 foreach(range(1, 12) as $month) {
   echo last_friday_of_month($year, $month), "
"; }

}

date_default_timezone_set("GMT"); $year = 2012; print_last_fridays_of_month($year); ?></lang>

Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

PicoLisp

<lang PicoLisp>(de lastFridays (Y)

  (for M 12
     (prinl
        (dat$
           (find '((D) (= "Friday" (day D)))
              (mapcar '((D) (date Y M D)) `(range 31 22)) )
           "-" ) ) ) )</lang>

Test: <lang PicoLisp>: (lastFridays 2012) 2012-01-27 2012-02-24 2012-03-30 2012-04-27 2012-05-25 2012-06-29 2012-07-27 2012-08-31 2012-09-28 2012-10-26 2012-11-30 2012-12-28</lang>

Pike

<lang Pike>int(0..1) last_friday(object day) {

  return day->week_day() == 5 && 
         day->month_day() > day->month()->number_of_days()-7; 

}

int main(int argc, array argv) {

   array days = filter(Calendar.Year((int)argv[1])->months()->days()[*], last_friday);
   write("%{%s\n%}", days->format_ymd());
   return 0;

}</lang>

PL/I

<lang PL/I> Fridays: procedure (year) options (main); /* 8 January 2013 */

  declare year character (4) varying;
  declare start fixed binary (31);
  declare months fixed decimal (2) initial (0);
  declare (current_month, month_one_week_hence) character (2);
  put list ('Last Fridays in each month for the year ' || year || ':' );
  start = days('0101' || year, 'DDMMYYYY');
  /* Find first Friday */
  do while (weekday(start) ^= 6); start = start + 1; end;
  do until (months=12);
     current_month = substr (daystodate(start, 'MMDDYYYY'), 1, 2 );
     month_one_week_hence = substr (daystodate(start+7, 'MMDDYYYY'), 1, 2 );
     if current_month ^= month_one_week_hence then
        do;
           months = months + 1;
           put skip list (daystodate(start, 'DDMmmYYYY'));
        end;
     start = start + 7;
  end;

end Fridays; </lang> The command: FRIDAYS /2008 produces:

Last Fridays in each month for the year 2008:
25Jan2008 
29Feb2008 
28Mar2008 
25Apr2008 
30May2008 
27Jun2008 
25Jul2008 
29Aug2008 
26Sep2008 
31Oct2008 
28Nov2008 
26Dec2008
Output:

for 2013

Last Fridays in each month for the year 2013: 
25Jan2013 
22Feb2013 
29Mar2013 
26Apr2013 
31May2013 
28Jun2013 
26Jul2013 
30Aug2013 
27Sep2013 
25Oct2013 
29Nov2013 
27Dec2013

Python

<lang python>import calendar c=calendar.Calendar() fridays={} year=raw_input("year") for item in c.yeardatescalendar(int(year)):

   for i1 in item:
       for i2 in i1:
           for i3 in i2:
               if "Fri" in i3.ctime() and year in i3.ctime():
                   month,day=str(i3).rsplit("-",1)
                   fridays[month]=day

for item in sorted((month+"-"+day for month,day in fridays.items()),

                  key=lambda x:int(x.split("-")[1])):
   print item</lang>

Using reduce

<lang python>import calendar c=calendar.Calendar() fridays={} year=raw_input("year") add=list.__add__ for day in reduce(add,reduce(add,reduce(add,c.yeardatescalendar(int(year))))):

   if "Fri" in day.ctime() and year in day.ctime():
       month,day=str(day).rsplit("-",1)
       fridays[month]=day

for item in sorted((month+"-"+day for month,day in fridays.items()),

                  key=lambda x:int(x.split("-")[1])):
   print item</lang>

using itertools

<lang python>import calendar from itertools import chain f=chain.from_iterable c=calendar.Calendar() fridays={} year=raw_input("year") add=list.__add__

for day in f(f(f(c.yeardatescalendar(int(year))))):

   if "Fri" in day.ctime() and year in day.ctime():
       month,day=str(day).rsplit("-",1)
       fridays[month]=day

for item in sorted((month+"-"+day for month,day in fridays.items()),

                  key=lambda x:int(x.split("-")[1])):
   print item</lang>

R

<lang rsplus>year = commandArgs(T) d = as.Date(paste0(year, "-01-01")) fridays = d + seq(by = 7,

   (5 - as.POSIXlt(d)$wday) %% 7,
   364 + (months(d + 30 + 29) == "February"))

message(paste(collapse = "\n", fridays[tapply(

   seq_along(fridays), as.POSIXlt(fridays)$mon, max)]))</lang>

Racket

<lang racket>

  1. lang racket

(require srfi/19 math)

(define (days-in-month m y)

 (define lengths #(0 31 #f 31 30 31 30 31 31 30 31 30 31))
 (define d (vector-ref lengths m))
 (or d (days-in-feb y)))

(define (leap-year? y)

 (and (divides? 4 y)
      (or (not (divides? 100 y))
          (divides? 400 y))))

(define (days-in-feb y)

 (if (leap-year? y) 29 28))

(define (last-day-in-month m y)

 (make-date 0 0 0 0 (days-in-month m y) m y 0))

(define (week-day date)

 (define days #(sun mon tue wed thu fri sat))
 (vector-ref days (date-week-day date)))

(define (last-fridays y)

 (for/list ([m (in-range 1 13)])
   (prev-friday (last-day-in-month m y))))

(define 24hours (make-time time-duration 0 (* 24 60 60)))

(define (prev-day d)

 (time-utc->date
  (subtract-duration 
   (date->time-utc d) 24hours)))

(define (prev-friday d)

 (if (eq? (week-day d) 'fri)
     d
     (prev-friday (prev-day d))))

(for ([d (last-fridays 2012)])

 (displayln (~a (date->string d "~a ~d ~b ~Y"))))

</lang>

Output:
Fri 27 Jan 2012
Fri 24 Feb 2012
Fri 30 Mar 2012
Fri 27 Apr 2012
Fri 25 May 2012
Fri 29 Jun 2012
Fri 27 Jul 2012
Fri 31 Aug 2012
Fri 28 Sep 2012
Fri 26 Oct 2012
Fri 30 Nov 2012
Fri 28 Dec 2012

REBOL

The longer version: <lang REBOL>leap-year?: function [year] [to-logic attempt [to-date reduce [29 2 year]]]

days-in-feb: function [year] [either leap-year? year [29] [28]]

days-in-month: function [month year] [

   do pick [31 (days-in-feb year) 31 30 31 30 31 31 30 31 30 31] month

]

last-day-of-month: function [month year] [

   to-date reduce [year month  days-in-month month year]

]

last-weekday-of-month: function [weekday month year] [

   d: last-day-of-month month year
   while [d/weekday != weekday] [d/day: d/day - 1]
   d

]

last-friday-of-month: function [month year] [last-weekday-of-month 5 month year]

year: to-integer input repeat month 12 [print last-friday-of-month month year] </lang>

Output:
rebol last-fridays.reb <<< 2012
27-Jan-2012
24-Feb-2012
30-Mar-2012
27-Apr-2012
25-May-2012
29-Jun-2012
27-Jul-2012
31-Aug-2012
28-Sep-2012
26-Oct-2012
30-Nov-2012
28-Dec-2012

A shorter version: <lang REBOL>last-fridays-of-year: function [year] [

   collect [
       repeat month 12 [
           d: to-date reduce [1 month year]
           d/month: d/month + 1                      ; start of next month
           until [d/day: d/day - 1  d/weekday = 5]   ; go backwards until find a Friday  
           keep d
       ]
   ]

]

foreach friday last-fridays-of-year to-integer input [print friday] </lang> NB. See "Find the last Sunday of each month" Rosetta for alternative (even more succinct) solution

REXX

This REXX program will find the last day-of-week (for any day) of all the months for any year.
It wasn't optimized just to find a particular day-of-week. <lang rexx>/*REXX program displays dates of last Fridays of each month for any year*/ parse arg yyyy

                  do j=1 for 12
                  say lastDOW('Friday',j,yyyy)
                  end  /*j*/

exit /*stick a fork in it, we're done.*/ /*┌────────────────────────────────────────────────────────────────────┐

 │ lastDOW:  procedure to return the date of the  last day-of-week of │
 │           any particular month  of any particular year.            │
 │                                                                    │
 │ The  day-of-week  must be specified (it can be in any case,        │
 │ (lower-/mixed-/upper-case)  as an English name of the spelled day  │
 │ of the week,   with a minimum length that causes no ambiguity.     │
 │ I.E.:   W  for Wednesday,   Sa  for Saturday,   Su  for Sunday ... │
 │                                                                    │
 │ The month can be specified as an integer   1 ──► 12                │
 │    1=January     2=February     3=March     ...     12=December    │
 │ or the English  name  of the month,  with a minimum length that    │
 │ causes no ambiguity.    I.E.:  Jun  for June,   D  for December.   │
 │ If omitted  [or an asterisk(*)],  the current month is used.       │
 │                                                                    │
 │ The year is specified as an integer or just the last two digits    │
 │ (two digit years are assumed to be in the current century,  and    │
 │ there is no windowing for a two-digit year).                       │
 │ If omitted  [or an asterisk(*)],  the current year is used.        │
 │ Years < 100   must be specified with  (at least 2)  leading zeroes.│
 │                                                                    │
 │ Method used: find the "day number" of the 1st of the next month,   │
 │ then subtract one  (this gives the "day number" of the last day of │
 │ the month,  bypassing the leapday mess).   The last day-of-week is │
 │ then obtained straightforwardly,   or  via subtraction.            │
 └────────────────────────────────────────────────────────────────────┘*/

lastdow: procedure; arg dow .,mm .,yy . /*DOW = day of week*/ parse arg a.1,a.2,a.3 /*orig args, errmsg*/ if mm== | mm=='*' then mm=left(date('U'),2) /*use default month*/ if yy== | yy=='*' then yy=left(date('S'),4) /*use default year */ if length(yy)==2 then yy=left(date('S'),2)yy /*append century. */

                  /*Note mandatory leading blank in strings below.*/

$=" Monday TUesday Wednesday THursday Friday SAturday SUnday" !=" JAnuary February MARch APril MAY JUNe JULy AUgust September",

 " October November December"

upper $ ! /*uppercase strings*/ if dow== then call .er "wasn't specified",1 if arg()>3 then call .er 'arguments specified',4

 do j=1 for 3                                       /*any plural args ?*/
 if words(arg(j))>1       then call .er 'is illegal:',j
 end

dw=pos(' 'dow,$) /*find day-of-week*/ if dw==0 then call .er 'is invalid:',1 if dw\==lastpos(' 'dow,$) then call .er 'is ambigious:',1

if datatype(mm,'month') then /*if MM is alpha...*/

 do
 m=pos(' 'mm,!)                                     /*maybe its good...*/
 if m==0                  then call .er 'is invalid:',1
 if m\==lastpos(' 'mm,!)  then call .er 'is ambigious:',2
 mm=wordpos(word(substr(!,m),1),!)-1                /*now, use true Mon*/
 end

if \datatype(mm,'W') then call .er "isn't an integer:",2 if \datatype(yy,'W') then call .er "isn't an integer:",3 if mm<1 | mm>12 then call .er "isn't in range 1──►12:",2 if yy=0 then call .er "can't be 0 (zero):",3 if yy<0 then call .er "can't be negative:",3 if yy>9999 then call .er "can't be > 9999:",3

tdow=wordpos(word(substr($,dw),1),$)-1 /*target DOW, 0──►6*/

                                                    /*day# of last dom.*/

_=date('B',right(yy+(mm=12),4)right(mm//12+1,2,0)"01",'S')-1 ?=_//7 /*calc. DOW, 0──►6*/ if ?\==tdow then _=_-?-7+tdow+7*(?>tdow) /*not DOW? Adjust.*/ return date('weekday',_,"B") date(,_,'B') /*return the answer*/

.er: arg ,_;say; say '***error!*** (in LASTDOW)';say /*tell error, and */

 say word('day-of-week month year excess',arg(2)) arg(1) a._
 say; exit 13                                       /*... then exit.   */</lang>
Output:

when using the following input

2012 or 12
Friday 27 Jan 2012
Friday 24 Feb 2012
Friday 30 Mar 2012
Friday 27 Apr 2012
Friday 25 May 2012
Friday 29 Jun 2012
Friday 27 Jul 2012
Friday 31 Aug 2012
Friday 28 Sep 2012
Friday 26 Oct 2012
Friday 30 Nov 2012
Friday 28 Dec 2012

Ruby

<lang ruby>require 'date'

def last_friday(year, month)

 # Last day of month: Date.new interprets a negative number as a relative month/day from the end of year/month.
 d = Date.new(year, month, -1)
 d -= (d.wday - 5) % 7  # Subtract days after Friday.

end

year = Integer(ARGV.shift) (1..12).each {|month| puts last_friday(year, month)}</lang>

Friday is d.wday == 5; the expression (d.wday - 5) % 7 counts days after Friday.

Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28
Library: ActiveSupport

Using the ActiveSupport library for some convenience methods

<lang ruby>require 'rubygems' require 'activesupport'

def last_friday(year, month)

 d = Date.new(year, month, 1).end_of_month
 until d.wday == 5
   d = d.yesterday
 end
 d

end</lang>

Run BASIC

<lang runbasic>input "Year:";yr dayOne$ = "01-01-";yr n1 = date$(dayOne$) for i = 1 to 12

 n1  = n1 + 26
 m1$ = left$(date$(n1),2)
 while  m1$ = left$(date$(n1),2) ' find end of month
   n1 = n1 + 1
 wend
 n1 = n1 -1
 while (n1 Mod 7) <> 3 	  ' find Friday
   n1 = n1 - 1
 wend
 print date$(n1)		  ' print last Friday's date

next i</lang>

Year:?2013
01/25/2013
02/22/2013
03/29/2013
04/26/2013
05/31/2013
06/28/2013
07/26/2013
08/30/2013
09/27/2013
10/25/2013
11/29/2013
12/27/2013

Scala

<lang scala>import java.util.Calendar import java.text.SimpleDateFormat

object Fridays {

 def lastFridayOfMonth(year:Int, month:Int)={
   val cal=Calendar.getInstance
   cal.set(Calendar.YEAR, year)
   cal.set(Calendar.MONTH, month)
   cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY)
   cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1)
   cal.getTime
 }
 def fridaysOfYear(year:Int)=for(month <- 0 to 11) yield lastFridayOfMonth(year, month)
 def main(args:Array[String]){
   val year=args(0).toInt
   val formatter=new SimpleDateFormat("yyyy-MMM-dd")
   fridaysOfYear(year).foreach{date=>
     println(formatter.format(date))
   }
 }

}</lang>

Output:
2012-Jan-27
2012-Feb-24
2012-Mrz-30
2012-Apr-27
2012-Mai-25
2012-Jun-29
2012-Jul-27
2012-Aug-31
2012-Sep-28
2012-Okt-26
2012-Nov-30
2012-Dez-28

Seed7

Uses the libraries time.s7i and duration.s7i. Applicable to any day of the week, cf. [[2]].

<lang seed7>$ include "seed7_05.s7i";

 include "time.s7i";
 include "duration.s7i";

const proc: main is func

 local
   var integer: weekday is 1; # 1 for monday, 2 for tuesday, and so on up to 7 for sunday.
   var integer: year is 0;
   var integer: month is 1;
   var time: aDate is time.value;
   var time: selected is time.value;
 begin
   if length(argv(PROGRAM)) <> 2 then
     writeln("usage: lastWeekdayInMonth weekday year");
     writeln("  weekday: 1 for monday, 2 for tuesday, and so on up to 7 for sunday.");
   else
     weekday := integer parse (argv(PROGRAM)[1]);
     year := integer parse (argv(PROGRAM)[2]);
     for month range 1 to 12 do
       aDate := date(year, month, 1);
       while aDate.month = month do
         if dayOfWeek(aDate) = weekday then
           selected := aDate;
         end if;
         aDate +:= 1 . DAYS;
       end while;
       writeln(strDate(selected));
     end for;
   end if;
 end func;</lang>
Output:

when called with s7 rosetta/lastWeekdayInMonth 5 2013

2013-01-25
2013-02-22
2013-03-29
2013-04-26
2013-05-31
2013-06-28
2013-07-26
2013-08-30
2013-09-27
2013-10-25
2013-11-29
2013-12-27

Tcl

<lang tcl>package require Tcl 8.5 set year [lindex $argv 0] foreach dm {02/1 03/1 04/1 05/1 06/1 07/1 08/1 09/1 10/1 11/1 12/1 12/32} {

   # The [clock scan] code is unhealthily clever; use it for our own evil purposes
   set t [clock scan "last friday" -base [clock scan $dm/$year -gmt 1] -gmt 1]
   # Print the interesting part
   puts [clock format $t -format "%Y-%m-%d" -gmt 1]

}</lang> Sample execution:

$ tclsh8.5 lastfri.tcl 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

TUSCRIPT

<lang tuscript> $$ MODE TUSCRIPT year=2012 LOOP month=1,12

LOOP day=31,22,-1
 dayofweek=DATE (number,day,month,year,nummer)
 IF (dayofweek==5) THEN
 PRINT year,"-",month,"-",day
 EXIT
 ENDIF
ENDLOOP

ENDLOOP </lang>

Output:
2012-1-27
2012-2-24
2012-3-30
2012-4-27
2012-5-25
2012-6-29
2012-7-27
2012-8-31
2012-9-28
2012-10-26
2012-11-30
2012-12-28

UNIX Shell

Using ncal. Will switch to Julian calender as ncal sees fit, and will not calculate past year 9999 (chances are you'll be too dead by then to worry about weekends anyway). <lang bash>#!/bin/sh

if [ -z $1 ]; then exit 1; fi

  1. weed out multiple erros due to bad year

ncal 1 $1 > /dev/null && \ for m in 01 02 03 04 05 06 07 08 09 10 11 12; do echo $1-$m-`ncal $m $1 | grep Fr | sed 's/.* \([0-9]\)/\1/'` done</lang>

Using date --date from GNU date??? This code is not portable.

<lang bash>#!/bin/sh

  1. Free code, no limit work
  2. $Id: lastfridays,v 1.1 2011/11/10 00:48:16 gilles Exp gilles $
  1. usage :
  2. lastfridays 2012 # prints last fridays of months of year 2012

debug=${debug:-false}

  1. debug=true

epoch_year_day() { #set -x x_epoch=`expr ${2:-0} '*' 86400 + 43200` date --date="${1:-1970}-01-01 UTC $x_epoch seconds" +%s }

year_of_epoch() { date --date="1970-01-01 UTC ${1:-0} seconds" +%Y } day_of_epoch() { LC_ALL=C date --date="1970-01-01 UTC ${1:-0} seconds" +%A } date_of_epoch() { date --date="1970-01-01 UTC ${1:-0} seconds" "+%Y-%m-%d" } month_of_epoch() { date --date="1970-01-01 UTC ${1:-0} seconds" "+%m" }

last_fridays() { year=${1:-2012}

       next_year=`expr $year + 1`
       $debug && echo "next_year $next_year"
       current_year=$year
       day=0
       previous_month=01
       while test $current_year != $next_year; do
       	$debug && echo "day $day"
       	current_epoch=`epoch_year_day $year $day`
       	$debug && echo "current_epoch $current_epoch"
       	current_year=`year_of_epoch $current_epoch`
       	current_day=`day_of_epoch $current_epoch`
       	$debug && echo "current_day $current_day"
       	test $current_day = 'Friday' && current_friday=`date_of_epoch $current_epoch`
       	$debug && echo "current_friday $current_friday"
       	current_month=`month_of_epoch $current_epoch`
       	$debug && echo "current_month $current_month"
       	# Change of month => previous friday is the last of month
       	test "$previous_month" != "$current_month" \
       		&& echo $previous_friday
       	
       	previous_month=$current_month
       	previous_friday=$current_friday
       	day=`expr $day + 1`
       done

}

  1. main

last_fridays ${1:-2012}</lang>

Sample execution:

lastfridays 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

Visual FoxPro

<lang vfp>

  • !* OOP implementaion

LOCAL lnYear As Integer, oCalc As fricalc CLEAR lnYear = VAL(INPUTBOX("Year", "Year")) oCalc = NEWOBJECT("fricalc") oCalc.LastFriday(lnYear)

DEFINE CLASS fricalc As Session DataSession = 2 && Private

PROCEDURE Init

  • !* These date settings are private to this class

SET DATE YMD SET CENTURY ON SET MARK TO "-" ENDPROC

FUNCTION LastFriday(tnYear As Integer) As VOID LOCAL i As Integer, ldDate As Date CLEAR ? "Last Fridays in the year " + TRANSFORM(tnYear) FOR i = 1 TO 12 ldDate = DATE(tnYear, i, 1) && 1st of month ldDate = GOMONTH(ldDate, 1) - 1 && last day of month *!* Use the built in function to return the day of the week *!* 6 is Friday DO WHILE DOW(ldDate) # 6 ldDate = ldDate - 1 ENDDO ? ldDate ENDFOR ENDFUNC

ENDDEFINE </lang>

XPL0

<lang XPL0>include c:\cxpl\codes; \intrinsic 'code' declarations

func WeekDay(Year, Month, Day); \Return day of week (0=Sun, 1=Mon ... 6=Sat) int Year, Month, Day; \works for years from 1583 onward [if Month<=2 then [Month:= Month+12; Year:= Year-1]; return rem((Day-1 + (Month+1)*26/10 + Year + Year/4 + Year/100*6 + Year/400)/7); ];

int Year, Month, LastDay, WD; [Year:= IntIn(8); \from command line for Month:= 1 to 12 do

   [LastDay:= WeekDay(Year, Month+1, 1) - WeekDay(Year, Month, 28);
   if LastDay < 0 then LastDay:= LastDay + 7;
   LastDay:= LastDay + 27;     \ = number of days in Month
   WD:= WeekDay(Year, Month, LastDay);
   WD:= WD - 5;
   if WD < 0 then WD:= WD + 7;
   LastDay:= LastDay - WD;
   IntOut(0, Year);  ChOut(0, ^-);
   if Month < 10 then ChOut(0, ^0);  IntOut(0, Month);  ChOut(0, ^-);
   IntOut(0, LastDay);  CrLf(0);
   ];

]</lang>

Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28

zkl

Gregorian calendar <lang zkl>var [const] D=Time.Date; fcn lastDay(y,_d){[1..12].pump(Console.println,

  'wrap(m){D.daysInMonth(y,m) :
     [_..1,-1].pump(Void,'wrap(d){
        D.weekDay(y,m,d) :
        if (_==_d)return(Void.Stop,"%d-%02d-%02d".fmt(y,m,d))
     })
  })

} lastDay(2012,D.Friday)</lang> For each month in year y, count back from the last day in the month until a Friday is found and print that date. A pump is a loop over a sequence and Void.Stop stops the pump with a value. The first parameter to a pump is the sink. All the imperative loop constructs are available but I didn't feel like using them. A wrap is a function closure over unknown values in the function, necessary because functions are not lexically scoped.

Output:
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28