Last Friday of each month: Difference between revisions
m make it look like we always intended it to be that way |
→{{header|Perl 6}}: new entry |
||
Line 479: | Line 479: | ||
2012-12-28 |
2012-12-28 |
||
</pre> |
</pre> |
||
=={{header|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] = $_ if .day-of-week == 5; |
|||
} |
|||
.Str.say for @fri[1..12]; |
|||
}</lang> |
|||
Example: |
|||
<pre>$ ./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</pre> |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
Revision as of 21:17, 20 January 2012
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.
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
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>
- 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++
called with ./last_fridays 2012
<lang cpp>#include <boost/date_time/gregorian/gregorian.hpp>
- include <iostream>
- 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
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>
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((11-d.Weekday())%7-6) * 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
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 friday within each represented month. 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
<lang java5>import java.text.DateFormatSymbols; import java.util.Calendar; import java.util.GregorianCalendar;
public class LastFriday {
private static int[] months = {Calendar.JANUARY, Calendar.FEBRUARY,
Calendar.MARCH, Calendar.APRIL, Calendar.MAY, Calendar.JUNE,
Calendar.JULY, Calendar.AUGUST, Calendar.SEPTEMBER, Calendar.OCTOBER,
Calendar.NOVEMBER, Calendar.DECEMBER};
public static void main(String[] args){
int year = Integer.parseInt(args[0]);
boolean leapYear = new GregorianCalendar().isLeapYear(year);
for(int month:months){
int days = 31;
switch(month){
case Calendar.SEPTEMBER:
case Calendar.APRIL:
case Calendar.JUNE:
case Calendar.NOVEMBER:
days = 30;
break;
case Calendar.FEBRUARY:
days = leapYear ? 29 : 28;
default:
}
GregorianCalendar date = new GregorianCalendar(year, month, days);
while(date.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY){
date.add(Calendar.DAY_OF_MONTH, -1);
}
String monthStr = new DateFormatSymbols().getShortMonths()[month];
System.out.println(monthStr +" "+ date.get(Calendar.DAY_OF_MONTH));
}
}
}</lang>
Output (for java LastFriday 2012
):
Jan 27 Feb 24 Mar 30 Apr 27 May 25 Jun 29 Jul 27 Aug 31 Sep 28 Oct 26 Nov 30 Dec 28
Mathematica
<lang Mathematica>Needs["Calendar`"] FridaysOfTheYear[Y_] := Cases[Map[{#,DayOfWeek[#]}&,DaysPlus[{Y,1,2}, #]&/@Range[365],{1}],List[x_,Friday]->x]; Last[SortBy[Cases[FridaysOfTheYear[2011], {_,#,_}], #3 &]]& /@ Range[12] // Column</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
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
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] = $_ if .day-of-week == 5; } .Str.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
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 in browser: <lang> 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>
PicoLisp
<lang PicoLisp>(de lastFridays (Y)
(for M `(range 1 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>
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>
Ruby
<lang ruby>require 'date'
def last_friday(year, month)
# Find end of month = beginning of month + 1 month - 1 day. d = Date.new(year, month, 1).>>(1) - 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.
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>
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
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
- 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
- Free code, no limit work
- $Id: lastfridays,v 1.1 2011/11/10 00:48:16 gilles Exp gilles $
- usage :
- lastfridays 2012 # prints last fridays of months of year 2012
debug=${debug:-false}
- 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
}
- 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