Day of the week
You are encouraged to solve this task according to the task description, using any language you may know.
A company decides that whenever Xmas falls on a Sunday they will give their workers all extra paid holidays so that, together with any public holidays, workers will not have to work the following week (between the 25th of December and the first of January).
In what years between 2008 and 2121 will the 25th of December be a Sunday?
Using any standard date handling libraries of your programming language; compare the dates calculated with the output of other languages to discover any anomalies in the handling of dates which may be due to, for example, overflow in types used to represent dates/times similar to y2k type problems.
[edit] ABAP
report zday_of_week
data: lv_start type i value 2007,
lv_n type i value 114,
lv_date type sy-datum,
lv_weekday type string,
lv_day type c,
lv_year type n length 4.
write 'December 25 is a Sunday in: '.
do lv_n times.
lv_year = lv_start + sy-index.
concatenate lv_year '12' '25' into lv_date.
call function 'DATE_COMPUTE_DAY'
exporting date = lv_date
importing day = lv_day.
select single langt from t246 into lv_weekday
where sprsl = sy-langu and
wotnr = lv_day.
if lv_weekday eq 'Sunday'.
write / lv_year.
endif.
enddo.
Output:
December 25 is a Sunday in: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Ada
with Ada.Calendar.Formatting; use Ada.Calendar.Formatting;
with Ada.Text_IO; use Ada.Text_IO;
procedure Yuletide is
begin
for Year in Ada.Calendar.Year_Number loop -- 1901..2399
if Day_Of_Week (Time_Of (Year, 12, 25)) = Sunday then
Put_Line (Image (Time_Of (Year, 12, 25)));
end if;
end loop;
end Yuletide;
Sample output:
1904-12-25 00:00:00 1910-12-25 00:00:00 1921-12-25 00:00:00 1927-12-25 00:00:00 1932-12-25 00:00:00 1938-12-25 00:00:00 1949-12-25 00:00:00 1955-12-25 00:00:00 1960-12-25 00:00:00 1966-12-25 00:00:00 1977-12-25 00:00:00 1983-12-25 00:00:00 1988-12-25 00:00:00 1994-12-25 00:00:00 2005-12-25 00:00:00 2011-12-25 00:00:00 2016-12-25 00:00:00 2022-12-25 00:00:00 2033-12-25 00:00:00 2039-12-25 00:00:00 2044-12-25 00:00:00 2050-12-25 00:00:00 2061-12-25 00:00:00 2067-12-25 00:00:00 2072-12-25 00:00:00 2078-12-25 00:00:00 2089-12-25 00:00:00 2095-12-25 00:00:00 2101-12-25 00:00:00 2107-12-25 00:00:00 2112-12-25 00:00:00 2118-12-25 00:00:00 2129-12-25 00:00:00 2135-12-25 00:00:00 2140-12-25 00:00:00 2146-12-25 00:00:00 2157-12-25 00:00:00 2163-12-25 00:00:00 2168-12-25 00:00:00 2174-12-25 00:00:00 2185-12-25 00:00:00 2191-12-25 00:00:00 2196-12-25 00:00:00 2203-12-25 00:00:00 2208-12-25 00:00:00 2214-12-25 00:00:00 2225-12-25 00:00:00 2231-12-25 00:00:00 2236-12-25 00:00:00 2242-12-25 00:00:00 2253-12-25 00:00:00 2259-12-25 00:00:00 2264-12-25 00:00:00 2270-12-25 00:00:00 2281-12-25 00:00:00 2287-12-25 00:00:00 2292-12-25 00:00:00 2298-12-25 00:00:00 2304-12-25 00:00:00 2310-12-25 00:00:00 2321-12-25 00:00:00 2327-12-25 00:00:00 2332-12-25 00:00:00 2338-12-25 00:00:00 2349-12-25 00:00:00 2355-12-25 00:00:00 2360-12-25 00:00:00 2366-12-25 00:00:00 2377-12-25 00:00:00 2383-12-25 00:00:00 2388-12-25 00:00:00 2394-12-25 00:00:00
[edit] ALGOL 68
# example from: http://www.xs4all.nl/~jmvdveer/algol.html - GPL #
INT sun=0 # , mon=1, tue=2, wed=3, thu=4, fri=5, sat=6 #;
PROC day of week = (INT year, month, day) INT: (
# Day of the week by Zeller’s Congruence algorithm from 1887 #
INT y := year, m := month, d := day, c;
IF m <= 2 THEN
m +:= 12; y -:= 1
FI;
c := y OVER 100;
y %*:= 100;
(d - 1 + ((m + 1) * 26) OVER 10 + y + y OVER 4 + c OVER 4 - 2 * c) MOD 7
);
test:(
print("December 25th is a Sunday in:");
FOR year FROM 2008 TO 2121 DO
INT wd = day of week(year, 12, 25);
IF wd = sun THEN print(whole(year,-5)) FI
OD;
new line(stand out)
)
Output:
December 25th is a Sunday in: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] AppleScript
set ChristmasSundays to {}
set Christmas to (current date)
set month of Christmas to December
set day of Christmas to 25
repeat with year from 2008 to 2121
set year of Christmas to year
if weekday of Christmas is Sunday then set end of ChristmasSundays to year
end repeat
ChristmasSundays
[edit] AutoHotkey
year = 2008
stop = 2121
While year <= stop {
FormatTime, day,% year 1225, dddd
If day = Sunday
out .= year "`n"
year++
}
MsgBox,% out
[edit] AutoIt
#include <date.au3>
Const $iSunday = 1
For $iYear = 2008 To 2121 Step 1
If $iSunday = _DateToDayOfWeek($iYear, 12, 25) Then
ConsoleWrite(StringFormat($iYear & "\n"))
EndIf
Next
[edit] AWK
# syntax: GAWK -f DAY_OF_THE_WEEK.AWK
# runtime does not support years > 2037 on my 32-bit Windows XP O/S
BEGIN {
for (i=2008; i<=2121; i++) {
x = strftime("%Y/%m/%d %a",mktime(sprintf("%d 12 25 0 0 0",i)))
if (x ~ /Sun/) { print(x) }
}
}
[edit] BBC BASIC
INSTALL @lib$+"DATELIB"
FOR year% = 2008 TO 2121
IF FN_dow(FN_mjd(25, 12, year%)) = 0 THEN
PRINT "Christmas Day is a Sunday in "; year%
ENDIF
NEXT
[edit] bc
Because bc has no date library, this program uses Zeller's rule, also known as Zeller's congruence, to calculate day of week.
scale = 0
/*
* Returns day of week (0 to 6) for year, month m, day d in proleptic
* Gregorian calendar. Sunday is 0. Assumes y >= 1, scale = 0.
*/
define w(y, m, d) {
auto a
/* Calculate Zeller's congruence. */
a = (14 - m) / 12
m += 12 * a
y -= a
return ((d + (13 * m + 8) / 5 + \
y + y / 4 - y / 100 + y / 400) % 7)
}
for (y = 2008; y <= 2121; y++) {
/* If December 25 is a Sunday, print year. */
if (w(y, 12, 25) == 0) y
}
quit
[edit] C
Because of problems with various C libraries (such as time_t overflowing during 2038, or strptime() or mktime() not filling in tm_wday), this program uses Zeller's Rule to calculate day of week.
#include <stdio.h>
/* Calculate day of week in proleptic Gregorian calendar. Sunday == 0. */
int wday(int year, int month, int day)
{
int adjustment, mm, yy;
adjustment = (14 - month) / 12;
mm = month + 12 * adjustment - 2;
yy = year - adjustment;
return (day + (13 * mm - 1) / 5 +
yy + yy / 4 - yy / 100 + yy / 400) % 7;
}
int main()
{
int y;
for (y = 2008; y <= 2121; y++) {
if (wday(y, 12, 25) == 0) printf("%04d-12-25\n", y);
}
return 0;
}
[edit] C++
#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>
int main( ) {
using namespace boost::gregorian ;
std::cout
<< "Yuletide holidays must be allowed in the following years:\n" ;
for ( int i = 2008 ; i < 2121 ; i++ ) {
greg_year gy = i ;
date d ( gy, Dec , 25 ) ;
if ( d.day_of_week( ) == Sunday ) {
std::cout << i << std::endl ;
}
}
std::cout << "\n" ;
return 0 ;
}
This produces the following output:
Yuletide holidays must be allowed in the following years: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] C#
using System;
class Program
{
static void Main(string[] args)
{
for (int i = 2008; i <= 2121; i++)
{
DateTime date = new DateTime(i, 12, 25);
if (date.DayOfWeek == DayOfWeek.Sunday)
{
Console.WriteLine(date.ToString("dd MMM yyyy"));
}
}
}
}
Using LINQ:
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
string[] days = (from day in
(from year in Enumerable.Range(2008, 2121 - 2007)
select new DateTime(year, 12, 25))
where day.DayOfWeek == DayOfWeek.Sunday
select day.ToString("dd MMM yyyy")).ToArray();
foreach (string day in days) Console.WriteLine(day);
}
}
This looks better:
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
string[] days = Enumerable.Range(2008, 2121 - 2007)
.Select(year => new DateTime(year, 12, 25))
.Where(day => day.DayOfWeek == DayOfWeek.Sunday)
.Select(day => day.ToString("dd MMM yyyy")).ToArray();
foreach (string day in days) Console.WriteLine(day);
}
}
Lambda expressions FTW:
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
Enumerable.Range(2008, 113).ToList()
.ConvertAll(ent => new DateTime(ent, 12, 25))
.Where(ent => ent.DayOfWeek.Equals(DayOfWeek.Sunday)).ToList()
.ForEach(ent => Console.WriteLine(ent.ToString("dd MMM yyyy")));
}
}
25 Dec 2011 25 Dec 2016 25 Dec 2022 25 Dec 2033 25 Dec 2039 25 Dec 2044 25 Dec 2050 25 Dec 2061 25 Dec 2067 25 Dec 2072 25 Dec 2078 25 Dec 2089 25 Dec 2095 25 Dec 2101 25 Dec 2107 25 Dec 2112 25 Dec 2118
[edit] Clojure
Utilizing Java interop
(import '(java.util GregorianCalendar))
(defn yuletide [start end]
(filter #(= (. (new GregorianCalendar %
(. GregorianCalendar DECEMBER) 25) get (. GregorianCalendar DAY_OF_WEEK))
(. GregorianCalendar SUNDAY)) (range start (inc end))))
(yuletide 2008 2121)
(2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118)
[edit] CoffeeScript
december = 11 # gotta love Date APIs :)
sunday = 0
for year in [2008..2121]
xmas = new Date year, december, 25
console.log year if xmas.getDay() is sunday
one-liner:
console.log year for year in [2008...2121] when new Date(year, 11, 25).getDay() is 0
output
2011
2016
2022
2033
2039
2044
2050
2061
2067
2072
2078
2089
2095
2101
2107
2112
2118
[edit] ColdFusion
<cfloop from = "2008" to = "2121" index = "i">
<cfset myDate = createDate(i, 12, 25) />
<cfif dayOfWeek(myDate) eq 1>
December 25th falls on a Sunday in <cfoutput>#i#</cfoutput><br />
</cfif>
</cfloop>
[edit] Common Lisp
(loop for year from 2008 upto 2121
when (= 6 (multiple-value-bind
(second minute hour date month year day-of-week dst-p tz)
(decode-universal-time (encode-universal-time 0 0 0 25 12 year))
day-of-week))
collect year)
[edit] D
import std.stdio, std.datetime, std.conv, std.algorithm, std.range;
void main() {
writeln("Christmas comes on a Sunday in the years:");
foreach (year; 2008 .. 2122) {
immutable d = text(year) ~ "-Dec-25";
if (Date.fromSimpleString(d).dayOfWeek() == DayOfWeek.sun)
writeln(year);
}
}
- Output:
Christmas comes on a Sunday in the years: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Delphi
procedure IsXmasSunday(fromyear, toyear: integer);
var
i: integer;
TestDate: TDateTime;
outputyears: string;
begin
outputyears := '';
for i:= fromyear to toyear do
begin
TestDate := EncodeDate(i,12,25);
if dayofweek(TestDate) = 1 then
begin
outputyears := outputyears + inttostr(i) + ' ';
end;
end;
form1.label1.caption := outputyears;
end;
Procedure called with year range to test and outputs a space-delimited array of years to a label. There is no error check that fromyear < toyear, but this is easily added.
output: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Euphoria
--Day of the week task from Rosetta Code wiki
--User:Lnettnay
--In what years between 2008 and 2121 will the 25th of December be a Sunday
include std/datetime.e
datetime dt
for year = 2008 to 2121 do
dt = new(year, 12, 25)
if weeks_day(dt) = 1 then -- Sunday = 1
? year
end if
end for
Output
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Factor
USING: calendar math.ranges prettyprint sequences ;
2008 2121 [a,b] [ 12 25 <date> sunday? ] filter .
[edit] Forth
Forth has only TIME&DATE, which does not give day of week. Many public Forth Julian date calculators had year-2100 problems, but this algorithm works well.
\ Zeller's Congruence
: zeller ( m -- days since March 1 )
9 + 12 mod 1- 26 10 */ 3 + ;
: weekday ( d m y -- 0..6 ) \ Monday..Sunday
over 3 < if 1- then
dup 4 /
over 100 / -
over 400 / + +
swap zeller + +
1+ 7 mod ;
: yuletide
." December 25 is Sunday in "
2122 2008 do
25 12 i weekday
6 = if i . then
loop cr ;
cr yuletide
December 25 is Sunday in 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
To show year-2100 problems with SwiftForth's provided Modified Julian Day support:
: yuletide
." December 25 is Sunday in "
2122 2008 do
25 12 i d/m/y
7 mod 0= if i . then
loop cr ;
cr yuletide
December 25 is Sunday in 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2100 2106 2117
[edit] Fortran
Based on Forth example
PROGRAM YULETIDE
IMPLICIT NONE
INTEGER :: day, year
WRITE(*, "(A)", ADVANCE="NO") "25th of December is a Sunday in"
DO year = 2008, 2121
day = Day_of_week(25, 12, year)
IF (day == 1) WRITE(*, "(I5)", ADVANCE="NO") year
END DO
CONTAINS
FUNCTION Day_of_week(d, m, y)
INTEGER :: Day_of_week, j, k
INTEGER, INTENT(IN) :: d, m, y
j = y / 100
k = MOD(y, 100)
Day_of_week = MOD(d + (m+1)*26/10 + k + k/4 + j/4 + 5*j, 7)
END FUNCTION Day_of_week
END PROGRAM YULETIDE
Output
25th of December is a Sunday in 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] GAP
xmas := function(a, b)
local y, v;
v := [ ];
for y in [a .. b] do
if WeekDay([25, 12, y]) = "Sun" then
Add(v, y);
fi;
od;
return v;
end;
xmas(2008, 2121);
# [ 2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118 ]
[edit] Go
package main
import "fmt"
import "time"
func main() {
for year := 2008; year <= 2121; year++ {
if time.Date(year, 12, 25, 0, 0, 0, 0, time.UTC).Weekday() ==
time.Sunday {
fmt.Printf("25 December %d is Sunday\n", year)
}
}
}
Output:
25 December 2011 is Sunday 25 December 2016 is Sunday 25 December 2022 is Sunday 25 December 2033 is Sunday 25 December 2039 is Sunday 25 December 2044 is Sunday 25 December 2050 is Sunday 25 December 2061 is Sunday 25 December 2067 is Sunday 25 December 2072 is Sunday 25 December 2078 is Sunday 25 December 2089 is Sunday 25 December 2095 is Sunday 25 December 2101 is Sunday 25 December 2107 is Sunday 25 December 2112 is Sunday 25 December 2118 is Sunday
[edit] Groovy
Solution:
def yuletide = { start, stop -> (start..stop).findAll { Date.parse("yyyy-MM-dd", "${it}-12-25").format("EEE") == "Sun" } }
Test program:
println yuletide(2008, 2121)
Output:
[2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118]
[edit] Haskell
Using the time library:
import Data.Time
import Data.Time.Calendar.WeekDate
isXmasSunday year = wday == 7
where (_,_,wday) = toWeekDate $ fromGregorian year 12 25
main = mapM_ putStrLn ["25 December " ++ show year ++ " is Sunday"
| year <- [2008..2121], isXmasSunday year]
Output:
25 December 2011 is Sunday 25 December 2016 is Sunday 25 December 2022 is Sunday 25 December 2033 is Sunday 25 December 2039 is Sunday 25 December 2044 is Sunday 25 December 2050 is Sunday 25 December 2061 is Sunday 25 December 2067 is Sunday 25 December 2072 is Sunday 25 December 2078 is Sunday 25 December 2089 is Sunday 25 December 2095 is Sunday 25 December 2101 is Sunday 25 December 2107 is Sunday 25 December 2112 is Sunday 25 December 2118 is Sunday
The built-in System.Time module overflows at the Unix epoch in 2038:
import System.Time
isXmasSunday year = ctWDay cal == Sunday
where cal = toUTCTime $ toClockTime cal'
cal' = CalendarTime {
ctYear = year,
ctMonth = December,
ctDay = 25,
ctHour = 0,
ctMin = 0,
ctSec = 0,
ctPicosec = 0,
ctWDay = Friday,
ctYDay = 0,
ctTZName = "",
ctTZ = 0,
ctIsDST = False
}
main = mapM_ putStrLn ["25 December " ++ show year ++ " is Sunday"
| year <- [2008..2121], isXmasSunday year]
Output on 32-bit machine:
25 December 2011 is Sunday 25 December 2016 is Sunday 25 December 2022 is Sunday 25 December 2033 is Sunday *** Exception: user error (Time.toClockTime: invalid input)
[edit] HicEst
DO year = 1, 1000000
TIME(Year=year, MOnth=12, Day=25, TO, WeekDay=weekday)
IF( weekday == 7) WRITE(StatusBar) year
ENDDO
END
No anomalies detected for the first million years :-)
Dec 25 = Sunday in
5 ... 2011 2016 2022 2033 2039 2044 2050 2061 2067
2072 2078 2089 2095 2101 2107 2112 2118 ... 999994
[edit] Icon and Unicon
link datetime
procedure main()
writes("December 25th is a Sunday in: ")
every writes((dayoweek(25,12,y := 2008 to 2122)=="Sunday",y)," ")
end
procedure dayoweek(day, month, year) #: day of the week
static d_code, c_code, m_code, ml_code, y, C, M, Y
initial {
d_code := ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
c_code := table()
c_code[16] := c_code[20] := 0
c_code[17] := c_code[21] := 6
c_code[18] := c_code[22] := 4
c_code[19] := c_code[23] := 2
m_code := table()
m_code[1] := m_code["January"] := 1
m_code[2] := m_code["February"] := 4
m_code[3] := m_code["March"] := 4
m_code[4] := m_code["April"] := 0
m_code[5] := m_code["May"] := 2
m_code[6] := m_code["June"] := 5
m_code[7] := m_code["July"] := 0
m_code[8] := m_code["August"] := 3
m_code[9] := m_code["September"] := 6
m_code[10] := m_code["October"] := 1
m_code[11] := m_code["November"] := 4
m_code[12] := m_code["December"] := 6
ml_code := copy(m_code)
ml_code[1] := ml_code["January"] := 0
ml_code[2] := ml_code["February"] := 3
}
if year < 1600 then stop("*** can't compute day of week that far back")
if year > 2299 then stop("*** can't compute day of week that far ahead")
C := c_code[(year / 100) + 1]
y := year % 100
Y := (y / 12) + (y % 12) + ((y % 12) / 4)
month := integer(month)
M := if (year % 4) = 0 then ml_code[month] else m_code[month]
return d_code[(C + Y + M + day) % 7 + 1]
end
Sample Output:
December 25th is a Sunday in: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] J
load 'dates' NB. provides verb 'weekday'
xmasSunday=: #~ 0 = [: weekday 12 25 ,~"1 0 ] NB. returns years where 25 Dec is a Sunday
xmasSunday 2008 + i.114 NB. check years from 2008 to 2121
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Java
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class Yuletide{
public static void main(String[] args) {
for(int i = 2008;i<=2121;i++){
Calendar cal = new GregorianCalendar(i, Calendar.DECEMBER,
25);
if(cal.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY){
System.out.println(cal.getTime());
}
}
}
}
Output:
Sun Dec 25 00:00:00 CST 2011 Sun Dec 25 00:00:00 CST 2016 Sun Dec 25 00:00:00 CST 2022 Sun Dec 25 00:00:00 CST 2033 Sun Dec 25 00:00:00 CST 2039 Sun Dec 25 00:00:00 CST 2044 Sun Dec 25 00:00:00 CST 2050 Sun Dec 25 00:00:00 CST 2061 Sun Dec 25 00:00:00 CST 2067 Sun Dec 25 00:00:00 CST 2072 Sun Dec 25 00:00:00 CST 2078 Sun Dec 25 00:00:00 CST 2089 Sun Dec 25 00:00:00 CST 2095 Sun Dec 25 00:00:00 CST 2101 Sun Dec 25 00:00:00 CST 2107 Sun Dec 25 00:00:00 CST 2112 Sun Dec 25 00:00:00 CST 2118
[edit] JavaScript
for (var year = 2008; year <= 2121; year++){
var xmas = new Date(year, 11, 25)
if ( xmas.getDay() === 0 )
console.log(year)
}
output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] K
wd:{(__jd x)!7} / Julian day count, Sun=6
y@&6={wd 1225+x*10000}'y:2008+!114
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Liberty BASIC
count = 0
for year = 2008 to 2121
dateString$="12/25/";year
dayNumber=date$(dateString$)
if dayNumber mod 7 = 5 then
count = count + 1
print dateString$
end if
next year
print count; " years when Christmas Day falls on a Sunday"
end
[edit] Lua
Library: LuaDate
require("date")
for year=2008,2121 do
if date(year, 12, 25):getweekday() == 1 then
print(year)
end
end
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] M4
divert(-1)
define(`for',
`ifelse($#,0,``$0'',
`ifelse(eval($2<=$3),1,
`pushdef(`$1',$2)$4`'popdef(`$1')$0(`$1',incr($2),$3,`$4')')')')
dnl julian day number corresponding to December 25th of given year
define(`julianxmas',
`define(`yrssince0',eval($1+4712))`'define(`noOfLpYrs',
eval((yrssince0+3)/4))`'define(`jd',
eval(365*yrssince0+noOfLpYrs-10-($1-1501)/100+($1-1201)/400+334+25-1))`'
ifelse(eval($1%4==0 && ($1%100!=0 || $1%400==0)),1,
`define(`jd',incr(jd))')`'jd')
divert
for(`yr',2008,2121,
`ifelse(eval(julianxmas(yr)%7==6),1,`yr ')')
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Mathematica
Reap[If[DateString[{#,12,25},"DayName"]=="Sunday",Sow[#]]&/@Range[2008,2121]][[2,1]]
gives back:
{2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118}
[edit] MATLAB / Octave
t = datenum([[2008:2121]',repmat([12,25,0,0,0], 2121-2007, 1)]);
t = t(strmatch('Sunday', datestr(t,'dddd')), :);
datestr(t,'yyyy')
Output:
ans = 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] 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]
)$
sublist(makelist(i, i, 2008, 2121),
lambda([y], weekday(y, 12, 25) = 'sunday));
/* [2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118] */
[edit] Modula-3
Modula-3 represents time using a (safe) wrapper around the C time interface. Consequently, it suffers from the same problem as C.
MODULE Yule EXPORTS Main;
IMPORT IO, Fmt, Date, Time;
VAR date: Date.T;
time: Time.T;
BEGIN
FOR year := 2008 TO 2121 DO
date.day := 25;
date.month := Date.Month.Dec;
date.year := year;
TRY
time := Date.ToTime(date);
EXCEPT
| Date.Error =>
IO.Put(Fmt.Int(year) & " is the last year we can specify\n");
EXIT;
END;
date := Date.FromTime(time);
IF date.weekDay = Date.WeekDay.Sun THEN
IO.Put("25th of December " & Fmt.Int(year) & " is Sunday\n");
END;
END;
END Yule.
Output:
25th of December 2011 is Sunday 25th of December 2016 is Sunday 25th of December 2022 is Sunday 25th of December 2033 is Sunday 2038 is the last year we can specify
[edit] MUMPS
Usage:
DOWHOLIDAY
;In what years between 2008 and 2121 will December 25 be a Sunday?
;Uses the VA's public domain routine %DTC (Part of the Kernel) named here DIDTC
NEW BDT,EDT,CHECK,CHKFOR,LIST,I,X,Y
;BDT - the beginning year to check
;EDT - the end year to check
;BDT and EDT are year offsets from the epoch date 1/1/1700
;CHECK - the month and day to look at
;CHKFOR - what day of the week to look for
;LIST - list of years in which the condition is true
;I - the year currently being checked
;X - the date in an "internal" format, for input to DOW^DIDTC
;Y - the output from DOW^DIDTC
SET BDT=308,EDT=421,CHECK="1225",CHKFOR=0,LIST=""
FOR I=BDT:1:EDT SET X=I_CHECK D DOW^DIDTC SET:(Y=0) LIST=$SELECT($LENGTH(LIST):LIST_", ",1:"")_(I+1700)
IF $LENGTH(LIST)=0 WRITE !,"There are no years that have Christmas on a Sunday in the given range."
IF $LENGTH(LIST) WRITE !,"The following years have Christmas on a Sunday: ",LIST
KILL BDT,EDT,CHECK,CHKFOR,LIST,I,X,Y
QUIT
USER>D ^DOWThe following years have Christmas on a Sunday: 2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118
[edit] NetRexx
/* NetRexx */
options replace format comments java crossref savelog symbols nobinary
yearRanges = [int 2008, 2121]
searchday = ''
cal = Calendar
loop year = yearRanges[0] to yearRanges[1]
cal = GregorianCalendar(year, Calendar.DECEMBER, 25)
dayIndex = cal.get(Calendar.DAY_OF_WEEK)
if dayIndex = Calendar.SUNDAY then searchday = searchday year
end year
say 'Between' yearRanges[0] 'and' yearRanges[1]', Christmas day falls on a Sunday on the following years:'
searchday = searchday.strip.changestr(' ', ',')
say ' 'searchday
return
- Output
Between 2008 and 2121, Christmas day falls on a Sunday on the following years: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
[edit] Comparison of Some Common Day-of-Week Algorithms
The following program exercises some common "Day-0f-Week" algorithms to confirm they all arrive at the same result.
/* NetRexx */
options replace format comments java crossref savelog symbols nobinary
days = 'Monday Tuesday Wednesday Thursday Friday Saturday Sunday'
yearRanges = [int 2008, 2121]
searchday = ''
searchday['index'] = days.wordpos('Sunday')
searchday[0] = 0
algorithmName = ['Java Calendar', 'Zeller[1]', 'Zeller[2]', 'Sakamoto', 'Gauss', 'Keith', 'Babwani']
loop alg = 0 to algorithmName.length - 1
sd = searchday[0] + 1
searchday[0] = sd
searchday['agorithm', sd] = algorithmName[alg]
loop year = yearRanges[0] to yearRanges[1]
select case alg
when 0 then dayIndex = getDaynumJavaLibrary(year, 12, 25)
when 1 then dayIndex = getDaynumZellersCongruenceMethod1(year, 12, 25)
when 2 then dayIndex = getDaynumZellersCongruenceMethod2(year, 12, 25)
when 3 then dayIndex = getDaynumSakamoto(year, 12, 25)
when 4 then dayIndex = getDaynumGauss(year, 12, 25)
when 5 then dayIndex = getDaynumKeith(year, 12, 25)
when 6 then dayIndex = getDaynumBabwani(year, 12, 25)
otherwise nop
end
if dayIndex = searchday['index'] then
searchday[sd] = searchday[sd] year
end year
end alg
-- display results
say 'Between' yearRanges[0] 'and' yearRanges[1]', Christmas day falls on a Sunday in the following years:'
loop r_ = 1 to searchday[0]
searchday[r_] = searchday[r_].strip.changestr(' ', ',')
say searchday['agorithm', r_].right(20)':' searchday[r_]
end r_
return
-- -----------------------------------------------------------------------------
method getDaynumJavaLibrary(Year = int, Month = int, Day = int, iso = Rexx 'Y') public static binary returns int
-- The day-of-week is an integer value where 1 is Sunday, 2 is Monday, ..., and 7 is Saturday
-- For an ISO week date Day-of-Week d (1 = Monday to 7 = Sunday), use d = ((h - 1 + 6) mod 7) + 1
cal = Calendar
jmNumber = [ -
Calendar.JANUARY, Calendar.FEBRUARY, Calendar.MARCH, Calendar.APRIL -
, Calendar.MAY, Calendar.JUNE, Calendar.JULY, Calendar.AUGUST -
, Calendar.SEPTEMBER, Calendar.OCTOBER, Calendar.NOVEMBER, Calendar.DECEMBER -
]
mon = jmNumber[Month - 1]
cal = GregorianCalendar(Year, mon, Day)
h = cal.get(Calendar.DAY_OF_WEEK)
if 'YES'.abbrev(iso.upper, 1) then w = ((h - 1 + 6) // 7) + 1
else w = h
return w
-- -----------------------------------------------------------------------------
method getDaynumZellersCongruenceMethod1(Year = int, Month = int, Day = int, iso = Rexx 'Y') public static returns int
-- DayNum results in an integer in the range 0-6 where 0 represents Monday etc.
-- For an ISO week date add 1
if Month = 1 | Month = 2 then do
Month = Month + 12
Year = Year - 1
end
MonthFactor = 2 * Month + 3 * (Month + 1) % 5
YearFactor = Year + Year % 4 - Year % 100 + Year % 400
DayNum = (Day + MonthFactor + YearFactor) // 7
if 'YES'.abbrev(iso.upper, 1) then d = DayNum + 1
else d = DayNum
return d
-- -----------------------------------------------------------------------------
method getDaynumZellersCongruenceMethod2(Year = int, Month = int, Day = int, iso = Rexx 'Y') public static binary returns int
-- h is the day of the week (0 = Saturday, 1 = Sunday, 2 = Monday, ...)
-- For an ISO week date Day-of-Week d (1 = Monday to 7 = Sunday), use d = ((h + 5) mod 7) + 1
if Month < 3 then do
Month = Month + 12
Year = Year - 1
end
q = Day
m = Month
Y = Year
h = (q + ((m + 1) * 26 % 10) + Y + (Y % 4) + 6 * (Y % 100) + (Y % 400)) // 7
if 'YES'.abbrev(iso.upper, 1) then d = ((h + 5) // 7) + 1
else d = h
return d
-- -----------------------------------------------------------------------------
method getDaynumSakamoto(y = int, m = int, d = int, iso = Rexx 'Y') public static binary returns int
-- h is the day of the week (0 = Sunday, 1 = Monday, 2 = Tuesday...)
-- For an ISO week date Day-of-Week d (1 = Monday to 7 = Sunday), use d = ((h + 6) mod 7) + 1
t = [int 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
y = y - (m < 3)
h = (y + y % 4 - y % 100 + y % 400 + t[m - 1] + d) // 7
if 'YES'.abbrev(iso.upper, 1) then d = ((h + 6) // 7) + 1
else d = h
return d
-- -----------------------------------------------------------------------------
method getDaynumGauss(Year = int, Month = int, Day = int, iso = Rexx 'Y') public static binary returns int
-- W is week day (0 = Sunday, ..., 6 = Saturday)
-- For an ISO week date Day-of-Week d (1 = Monday to 7 = Sunday), use d = ((h + 6) mod 7) + 1
Year = Year - (Month < 3)
k = double Day
C = double Year % 100
Y = double Year // 100
m = double ((Month + 9) // 12) + 1
W = modulo(int (k + Math.floor(2.6 * m - 0.2) + y + Math.floor(y / 4) + Math.floor(c / 4) - 2 * c), 7)
if 'YES'.abbrev(iso.upper, 1) then h = ((W + 6) // 7) + 1
else h = W
return h
-- -----------------------------------------------------------------------------
method getDaynumKeith(y = int, m = int, d = int, iso = Rexx 'Y') public constant binary returns int
-- W is week day (0 = Sunday, ..., 6 = Saturday)
-- For an ISO week date Day-of-Week d (1 = Monday to 7 = Sunday), use d = ((h + 6) mod 7) + 1
if m < 3 then do
d = d + y
y = y - 1
end
else do
d = d + y - 2
end
h = (23 * m % 9 + d + 4 + y % 4 - y % 100 + y % 400) // 7
if 'YES'.abbrev(iso.upper, 1) then W = ((h + 6) // 7) + 1
else W = h
return W
-- -----------------------------------------------------------------------------
method getDaynumBabwani(Year = int, Month = int, Day = int, iso = Rexx 'Y') public constant binary returns int
-- return dow = Day of week: 0 = Saturday, 1 = Sunday, ... 6 = Friday
-- For an ISO week date Day-of-Week W (1 = Monday to 7 = Sunday), use W = ((dow + 5) mod 7) + 1
y = Year
m = Month
d = Day
dow = int -- dow stands for day of week
dowfg = double
fmonth = int
leap = int
if ((y // 100 == 0) & (y // 400 \= 0)) then -- leap function 1 for leap & 0 for non-leap
leap = 0
else if (y // 4 == 0) then
leap = 1
else
leap = 0
fmonth = 3 + (2 - leap) * ((m + 2) % (2 * m)) + (5 * m + m % 9) % 2 -- f(m) formula
fmonth = fmonth // 7 -- f(m) is brought in range of 0 to 6
century = y % 100
lastdigits = y // 100
dowfg = 1.25 * lastdigits + fmonth + d - 2 * (century // 4) -- function of weekday for Gregorian
dow = int dowfg // 7 -- remainder on division by 7
if 'YES'.abbrev(iso.upper, 1) then W = ((dow + 5) // 7) + 1
else W = dow
return W
-- -----------------------------------------------------------------------------
method modulo(N = int, D = int) inheritable static binary returns int
return (D + (N // D)) // D
- Output
Between 2008 and 2121, Christmas day falls on a Sunday in the following years:
Java Calendar: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
Zeller[1]: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
Zeller[2]: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
Sakamoto: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
Gauss: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
Keith: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
Babwani: 2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118
[edit] Objective-C
It should works also with Cocoa and OpenStep in general, but I can't test these.
#import <Foundation/Foundation.h>
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSUInteger i;
for(i=2008; i<2121; i++)
{
NSCalendarDate *d = [[NSCalendarDate alloc]
initWithYear: i
month: 12
day: 25
hour: 0 minute: 0 second:0
timeZone: [NSTimeZone timeZoneWithAbbreviation:@"CET"] ];
if ( [d dayOfWeek] == 0 )
{
printf("25 Dec %u is Sunday\n", i);
}
[d release];
}
[pool release];
return 0;
}
Output:
25 Dec 2011 is Sunday 25 Dec 2016 is Sunday 25 Dec 2022 is Sunday 25 Dec 2033 is Sunday 25 Dec 2039 is Sunday 25 Dec 2044 is Sunday 25 Dec 2050 is Sunday 25 Dec 2061 is Sunday 25 Dec 2067 is Sunday 25 Dec 2072 is Sunday 25 Dec 2078 is Sunday 25 Dec 2089 is Sunday 25 Dec 2095 is Sunday 25 Dec 2101 is Sunday 25 Dec 2107 is Sunday 25 Dec 2112 is Sunday 25 Dec 2118 is Sunday
[edit] OCaml
#load "unix.cma"
open Unix
try
for i = 2008 to 2121 do
(* I'm lazy so we'll just borrow the current time
instead of having to set all the fields explicitly *)
let mytime = { (localtime (time ())) with
tm_year = i - 1900;
tm_mon = 11;
tm_mday = 25 } in
try
let _, mytime = mktime mytime in
if mytime.tm_wday = 0 then
Printf.printf "25 December %d is Sunday\n" i
with e ->
Printf.printf "%d is the last year we can specify\n" (i-1);
raise e
done
with _ -> ()
The output of a run on a 32 bit machine is
25 December 2011 is Sunday 25 December 2016 is Sunday 25 December 2022 is Sunday 25 December 2033 is Sunday 2037 is the last year we can specify
[edit] With a dedicated library
Unlike the previous example which only uses the OCaml standard library, here with the OCaml Calendar Library we can go until the year 2121:
open CalendarLib
let list_make_seq first last =
let rec aux i acc =
if i < first then acc
else aux (pred i) (i::acc)
in
aux last []
let print_date (year, month, day) =
Printf.printf "%d-%02d-%02d\n" year month day
let () =
let years = list_make_seq 2008 2121 in
let years = List.filter (fun year ->
Date.day_of_week (Date.make year 12 25) = Date.Sun) years in
print_endline "December 25 is a Sunday in:";
List.iter (Printf.printf "%d\n") years
Output:
$ ocaml unix.cma str.cma -I +calendar calendarLib.cma xmas_sundays.ml December 25 is a Sunday in: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Pascal
See Delphi
[edit] Perl
#! /usr/bin/perl -w
use Time::Local;
use strict;
foreach my $i (2008 .. 2121)
{
my $time = timelocal(0,0,0,25,11,$i);
my ($s,$m,$h,$md,$mon,$y,$wd,$yd,$is) = localtime($time);
if ( $wd == 0 )
{
print "25 Dec $i is Sunday\n";
}
}
exit 0;
Output:
25 Dec 2011 is Sunday 25 Dec 2016 is Sunday 25 Dec 2022 is Sunday 25 Dec 2033 is Sunday Day too big - 25195 > 24855 Sec too small - 25195 < 78352 Sec too big - 25195 > 15247 Cannot handle date (0, 0, 0, 25, 11, 2038) at ./ydate.pl line 8
Using the DateTime module from CPAN:
#! /usr/bin/perl -w
use DateTime;
use strict;
foreach my $i (2008 .. 2121)
{
my $dt = DateTime->new( year => $i,
month => 12,
day => 25
);
if ( $dt->day_of_week == 7 )
{
print "25 Dec $i is Sunday\n";
}
}
exit 0;
or shorter:
#! /usr/bin/perl -w
use DateTime;
use strict;
for (2008 .. 2121) {
print "25 Dec $_ is Sunday\n"
if DateTime->new(year => $_, month => 12, day => 25)->day_of_week == 7;
}
exit 0;
Output:
25 Dec 2011 is Sunday 25 Dec 2016 is Sunday 25 Dec 2022 is Sunday 25 Dec 2033 is Sunday 25 Dec 2039 is Sunday 25 Dec 2044 is Sunday 25 Dec 2050 is Sunday 25 Dec 2061 is Sunday 25 Dec 2067 is Sunday 25 Dec 2072 is Sunday 25 Dec 2078 is Sunday 25 Dec 2089 is Sunday 25 Dec 2095 is Sunday 25 Dec 2101 is Sunday 25 Dec 2107 is Sunday 25 Dec 2112 is Sunday 25 Dec 2118 is Sunday
Alternatively in one line using grep (read from right to left):
#! /usr/bin/perl -w
use DateTime;
use strict;
print join " ", grep { DateTime->new(year => $_, month => 12, day => 25)->day_of_week == 7 } (2008 .. 2121);
0;
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Perl 6
As Perl 5, except DateTime is built-in, so you don't need to download a module of that name:
say join ' ', grep { Date.new($_, 12, 25).day-of-week == 7 }, 2008 .. 2121;
[edit] PHP
<?php
for($i=2008; $i<2121; $i++)
{
$datetime = new DateTime("$i-12-25 00:00:00");
if ( $datetime->format("w") == 0 )
{
echo "25 Dec $i is Sunday\n";
}
}
?>
Output:
25 Dec 2011 is Sunday 25 Dec 2016 is Sunday 25 Dec 2022 is Sunday 25 Dec 2033 is Sunday 25 Dec 2039 is Sunday 25 Dec 2044 is Sunday 25 Dec 2050 is Sunday 25 Dec 2061 is Sunday 25 Dec 2067 is Sunday 25 Dec 2072 is Sunday 25 Dec 2078 is Sunday 25 Dec 2089 is Sunday 25 Dec 2095 is Sunday 25 Dec 2101 is Sunday 25 Dec 2107 is Sunday 25 Dec 2112 is Sunday 25 Dec 2118 is Sunday
[edit] PicoLisp
(for (Y 2008 (>= 2121 Y) (inc Y))
(when (= "Sunday" (day (date Y 12 25)))
(printsp Y) ) )
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Pike
filter(Calendar.Year(2008)->range(Calendar.Year(2121))->years()->month(12)->day(25), lambda(object day){ return day->week_day()==7; })->year()->format_nice();
Output:
Result: ({ /* 17 elements */
"2011",
"2016",
"2022",
"2033",
"2039",
"2044",
"2050",
"2061",
"2067",
"2072",
"2078",
"2089",
"2095",
"2101",
"2107",
"2112",
"2118"
})
[edit] PL/I
declare i picture '9999';
do i = 2008 to 2121;
if weekday(days('25Dec' || i, 'DDMmmYYYY')) = 1 then
put skip list ('Christmas day ' || i || ' is a Sunday');
end;
[edit] PowerShell
2008..2121 | Where-Object { (Get-Date $_-12-25).DayOfWeek -eq "Sunday" }
[edit] Protium
<@ SAI>
<@ ITEFORLI3>2121|2008|
<@ LETVARCAP>Christmas Day|25-Dec-<@ SAYVALFOR>...</@></@>
<@ TSTDOWVARLIT>Christmas Day|1</@>
<@ IFF>
<@ SAYCAP>Christmas Day <@ SAYVALFOR>...</@> is a Sunday</@><@ SAYKEY>__Newline</@>
</@>
</@>
</@>
English dialect variable-length space-padded opcodes
<# suppressimplicitoutput>
<# iterate foriteration literalstring3>2121|2008|
<# let variable capture>Christmas Day|25-Dec-<# say value foriteration>...</#></#>
<# test dayofweek variable literal>Christmas Day|1</#>
<# if>
<# say capture>Christmas Day <# say value foriteration>...</#> is a Sunday</#><# say keyword>__Newline</#>
</#>
</#>
</#>
Output
Christmas Day 2011 is a Sunday Christmas Day 2016 is a Sunday Christmas Day 2022 is a Sunday Christmas Day 2033 is a Sunday Christmas Day 2039 is a Sunday Christmas Day 2044 is a Sunday Christmas Day 2050 is a Sunday Christmas Day 2061 is a Sunday Christmas Day 2067 is a Sunday Christmas Day 2072 is a Sunday Christmas Day 2078 is a Sunday Christmas Day 2089 is a Sunday Christmas Day 2095 is a Sunday Christmas Day 2101 is a Sunday Christmas Day 2107 is a Sunday Christmas Day 2112 is a Sunday Christmas Day 2118 is a Sunday
[edit] PureBasic
PureBasic's internal Date() is limited between 1970-01-01 00:00:00 and 2038-01-19 03:14:07
For i=2008 To 2037
If DayOfWeek(Date(i,12,25,0,0,0))=0
PrintN(Str(i))
EndIf
Next
[edit] Python
import datetimeOutput:
def yuletide():
sunday = 6
days = (day.strftime('%d %b %Y') for day in (datetime.date(year, 12, 25) for year in range(2008,2122)) if day.weekday() == sunday)
print '\n'.join(days)
yuletide()
25 Dec 2011 25 Dec 2016 25 Dec 2022 25 Dec 2033 25 Dec 2039 25 Dec 2044 25 Dec 2050 25 Dec 2061 25 Dec 2067 25 Dec 2072 25 Dec 2078 25 Dec 2089 25 Dec 2095 25 Dec 2101 25 Dec 2107 25 Dec 2112 25 Dec 2118
[edit] R
years <- 2008:2121
xmas <- as.POSIXlt(paste(years, '/12/25', sep=""))
years[xmas$wday==0]
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
Also:
xmas=seq(as.Date("2008/12/25"), as.Date("2121/12/25"), by="year")
as.numeric(format(xmas[weekdays(xmas)== 'Sunday'], "%Y"))
#Still another solution, using ISOdate and weekdays
(2008:2121)[weekdays(ISOdate(2008:2121, 12, 25)) == "Sunday"]
# Simply replace "Sunday" with whatever it's named in your country,
# or set locale first, with
Sys.setlocale(cat="LC_ALL", "en")
[edit] REBOL
rebol [
Title: "Yuletide Holiday"
Author: oofoe
Date: 2009-12-07
URL: http://rosettacode.org/wiki/Yuletide_Holiday
]
for y 2008 2121 1 [
d: to-date reduce [y 12 25]
if 7 = d/weekday [prin [y ""]]
]
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] REXX
[edit] version 1
do year = 2008 to 2121
if date('w', year'1225', 's') = 'Sunday' then say year
end
[edit] version 2
Alternative:
do year = 2008 to 2121
if date('b', year'1225', 's') // 7 = 6 then say year
end
Output from either:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] version 3
The extended DATE parameters (arguments 2 and 3) are only supported by the
newer REXX interpreters.
Language note: the DATE built-in function always returns the day-of-week in English,
no matter what the native language is in effect.
/*REXX program displays which years December 25th falls on a Sunday. */
parse arg start finish . /*get the start and finish years.*/
if start=='' then start=2008 /*None specified? Assume default*/
if finish=='' then finish=2121 /*None specified? Assume default*/
do y=start to finish /*process the years specified. */
if date('Weekday',y"-12-25",'ISO')\=='Sunday' then iterate
/* if date('w' ,y"-12-25",'i' )\== ... (same as above). */
/* option yyyy-mm-dd fmt */
say 'December 25th,' y "falls on a Sunday."
end
Output (using the defaults):
December 25th, 2011 falls on a Sunday. December 25th, 2016 falls on a Sunday. December 25th, 2022 falls on a Sunday. December 25th, 2033 falls on a Sunday. December 25th, 2039 falls on a Sunday. December 25th, 2044 falls on a Sunday. December 25th, 2050 falls on a Sunday. December 25th, 2061 falls on a Sunday. December 25th, 2067 falls on a Sunday. December 25th, 2072 falls on a Sunday. December 25th, 2078 falls on a Sunday. December 25th, 2089 falls on a Sunday. December 25th, 2095 falls on a Sunday. December 25th, 2101 falls on a Sunday. December 25th, 2107 falls on a Sunday. December 25th, 2112 falls on a Sunday. December 25th, 2118 falls on a Sunday.
[edit] version 4
This version will work with any version of a REXX interpreter.
/*REXX program (old school) displays which years 12/25 falls on a Sunday*//
parse arg start finish . /*get the start and finish years.*/
if start=='' then start=2008 /*None specified? Assume default*/
if finish=='' then finish=2121 /*None specified? Assume default*/
do y=start to finish /*process the years specified. */
if dow(12,25,y)==1 then say 'December 25th,' y "falls on a Sunday."
end
exit
/*─────────────────────────────────────DOW (day of week) subroutine─────*/
dow: procedure; arg m,d,y; if m<3 then do; m=m+12; y=y-1; end
yL=left(y,2); yr=right(y,2); w=(d+(m+1)*26%10+yr+yr%4+yL%4+5*yL)//7
if w==0 then w=7; return w /*Sunday=1, Monday=2, ... Saturday=7*/
Output (using the defaults):
December 25th, 2011 falls on a Sunday. December 25th, 2016 falls on a Sunday. December 25th, 2022 falls on a Sunday. December 25th, 2033 falls on a Sunday. December 25th, 2039 falls on a Sunday. December 25th, 2044 falls on a Sunday. December 25th, 2050 falls on a Sunday. December 25th, 2061 falls on a Sunday. December 25th, 2067 falls on a Sunday. December 25th, 2072 falls on a Sunday. December 25th, 2078 falls on a Sunday. December 25th, 2089 falls on a Sunday. December 25th, 2095 falls on a Sunday. December 25th, 2101 falls on a Sunday. December 25th, 2107 falls on a Sunday. December 25th, 2112 falls on a Sunday. December 25th, 2118 falls on a Sunday.
[edit] Ruby
require 'date'
(2008..2121).each do |year|
puts "25 Dec #{year}" if Date.new(year, 12, 25).wday == 0 # Ruby 1.9: if Date.new(year, 12, 25).sunday?
end
Output:
25 Dec 2011 25 Dec 2016 25 Dec 2022 25 Dec 2033 25 Dec 2039 25 Dec 2044 25 Dec 2050 25 Dec 2061 25 Dec 2067 25 Dec 2072 25 Dec 2078 25 Dec 2089 25 Dec 2095 25 Dec 2101 25 Dec 2107 25 Dec 2112 25 Dec 2118
The Time class overflows at the Unix epoch in 2038:
SUNDAY = 0
(2008..2121).each do |year|
begin
day = Time.local(year, 12, 25)
puts "25 Dec #{year}" if day.wday == SUNDAY # Ruby 1.9: if day.sunday?
rescue ArgumentError
puts '%d is the last year we can specify' % (year-1)
break
end
end
Output on 32-bit machine:
25 Dec 2011 25 Dec 2016 25 Dec 2022 25 Dec 2033 2037 is the last year we can specify
[edit] Run BASIC
for year = 2008 to 2121
if val(date$("12-25-";year)) mod 7 = 5 then print "For ";year;"xmas is Sunday"
next year
For 2011 xmas is Sunday For 2016 xmas is Sunday For 2022 xmas is Sunday For 2033 xmas is Sunday For 2039 xmas is Sunday For 2044 xmas is Sunday For 2050 xmas is Sunday For 2061 xmas is Sunday For 2067 xmas is Sunday For 2072 xmas is Sunday For 2078 xmas is Sunday For 2089 xmas is Sunday For 2095 xmas is Sunday For 2101 xmas is Sunday For 2107 xmas is Sunday For 2112 xmas is Sunday For 2118 xmas is Sunday
[edit] SAS
data _null_;
do y=2008 to 2121;
a=mdy(12,25,y);
if weekday(a)=1 then put y;
end;
run;
/* 2011 2016 2022 2033 2039 2044 2050 2061 2067
2072 2078 2089 2095 2101 2107 2112 2118 */
[edit] Scala
Output:
import java.util.{Calendar, GregorianCalendar}
import Calendar._
object DayOfTheWeek {
def main(args:Array[String]) {
for (year <- 2008 to 2121;
date <- Some(new GregorianCalendar(year, DECEMBER, 25));
if date.get(DAY_OF_WEEK) == SUNDAY) {
println(year)
}
}
}
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Scheme
(define (day-of-week year month day)
(if (< month 3)
(begin (set! month (+ month 12)) (set! year (- year 1))))
(+ 1
(remainder (+ 5 day (quotient (* (+ 1 month) 13) 5)
year (quotient year 4) (* (quotient year 100) 6) (quotient year 400))
7)))
(define (task)
(let loop ((y 2121) (v '()))
(if (< y 2008)
v
(loop (- y 1)
(if (= 7 (day-of-week y 12 25))
(cons y v)
v)))))
(task)
; (2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118)
[edit] Seed7
$ include "seed7_05.s7i";
include "time.s7i";
const proc: main is func
local
var integer: year is 0;
begin
for year range 2008 to 2122 do
if dayOfWeek(date(year, 12, 25)) = 7 then
writeln("Christmas comes on a sunday in " <& year);
end if;
end for;
end func;
Output:
Christmas comes on a sunday in 2011 Christmas comes on a sunday in 2016 Christmas comes on a sunday in 2022 Christmas comes on a sunday in 2033 Christmas comes on a sunday in 2039 Christmas comes on a sunday in 2044 Christmas comes on a sunday in 2050 Christmas comes on a sunday in 2061 Christmas comes on a sunday in 2067 Christmas comes on a sunday in 2072 Christmas comes on a sunday in 2078 Christmas comes on a sunday in 2089 Christmas comes on a sunday in 2095 Christmas comes on a sunday in 2101 Christmas comes on a sunday in 2107 Christmas comes on a sunday in 2112 Christmas comes on a sunday in 2118
[edit] Smalltalk
2008 to: 2121 do: [ :year | |date|
date := Date newDay: 25 monthIndex: 12 year: year.
date dayName = #Sunday
ifTrue: [ date displayNl ]
]
Output:
25-Dec-2011 25-Dec-2016 25-Dec-2022 25-Dec-2033 25-Dec-2039 25-Dec-2044 25-Dec-2050 25-Dec-2061 25-Dec-2067 25-Dec-2072 25-Dec-2078 25-Dec-2089 25-Dec-2095 25-Dec-2101 25-Dec-2107 25-Dec-2112 25-Dec-2118
[edit] Suneido
year = 2008
while (year <= 2121)
{
if Date('#' $ year $ '1225').WeekDay() is 0
Print(year)
++year
}
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Tcl
package require Tcl 8.5
for {set y 2008} {$y <= 2121} {incr y} {
if {[clock format [clock scan "$y-12-25" -format {%Y-%m-%d}] -format %w] == 0} {
puts "xmas $y is a sunday"
}
}
outputs
xmas 2011 is a sunday xmas 2016 is a sunday xmas 2022 is a sunday xmas 2033 is a sunday xmas 2039 is a sunday xmas 2044 is a sunday xmas 2050 is a sunday xmas 2061 is a sunday xmas 2067 is a sunday xmas 2072 is a sunday xmas 2078 is a sunday xmas 2089 is a sunday xmas 2095 is a sunday xmas 2101 is a sunday xmas 2107 is a sunday xmas 2112 is a sunday xmas 2118 is a sunday
[edit] TI-83 BASIC
Works with TI-84+/SE only
:For(A, 2008,2121
:dayofWk(A,12,25
:If Ans=1
:Disp A
:End
outputs
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118 Done
[edit] TUSCRIPT
$$ MODE TUSCRIPT
PRINT "25th of December will be a Sunday in the following years: "
LOOP year=2008,2121
SET dayofweek = DATE (number,25,12,year,nummer)
IF (dayofweek==7) PRINT year
ENDLOOP
Output:
25th of December will be a Sunday in the following years: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] UNIX Shell
Unix commands may use time_t to count seconds since the epoch. For systems with 32-bit time, the counter overflows during 19 January 2038. These scripts continue to 2121 and may need a system with 64-bit time, to prevent the overflow.
[edit] With GNU date
This solution uses date -d, which seems to be a GNU extension, so it only works with those systems.
#! /bin/bash
for (( i=2008; i<=2121; ++i ))
do
date -d "$i-12-25"
done |grep Sun
exit 0
The first lines of output (from a GNU/Linux system with 32bit time_t, date version 6.9) are
Sun Dec 25 00:00:00 CET 2011
Sun Dec 25 00:00:00 CET 2016
Sun Dec 25 00:00:00 CET 2022
Sun Dec 25 00:00:00 CET 2033
date: invalid date `2038-12-25'
I.e., starting from year 2038, the date command (which uses the glibc library, at least on GNU systems), is not able to recognise the date as a valid one!
Different machine/OS version (64 bit time_t): This is the same command run on RedHat Linux.
bash-3.00$ date --version
date (coreutils) 5.2.1
Written by David MacKenzie.
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
bash-3.00$ uname -a
Linux brslln01 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux
bash-3.00$ for((i=2009; i <= 2121; i++)); do date -d "$i-12-25" |egrep Sun; done
Sun Dec 25 00:00:00 GMT 2011
Sun Dec 25 00:00:00 GMT 2016
Sun Dec 25 00:00:00 GMT 2022
Sun Dec 25 00:00:00 GMT 2033
Sun Dec 25 00:00:00 GMT 2039
Sun Dec 25 00:00:00 GMT 2044
Sun Dec 25 00:00:00 GMT 2050
Sun Dec 25 00:00:00 GMT 2061
Sun Dec 25 00:00:00 GMT 2067
Sun Dec 25 00:00:00 GMT 2072
Sun Dec 25 00:00:00 GMT 2078
Sun Dec 25 00:00:00 GMT 2089
Sun Dec 25 00:00:00 GMT 2095
Sun Dec 25 00:00:00 GMT 2101
Sun Dec 25 00:00:00 GMT 2107
Sun Dec 25 00:00:00 GMT 2112
Sun Dec 25 00:00:00 GMT 2118
bash-3.00$
[edit] With GNU date and GNU seq (UnixPipes)
Like the previous solution, this solution uses date -d, which seems to be a GNU extension. Output is same as previous solution.
seq 2008 2121 | xargs -IYEAR -n 1 date +%c -d 'Dec 25 YEAR' | grep Sun
[edit] With Unix cal
The cal command is a tradition since Version 6 AT&T UNIX. This solution assumes that cal will always output a calendar in this format.
$ cal 12 2011
December 2011
Su Mo Tu We Th Fr Sa
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
This format always puts Sunday in columns 1 and 2. The solution uses tail to delete the first 2 lines (month, year, names of days), cut to extract Sunday's columns, and grep to check if "25" appears in those columns.
y=2008
while test $y -lt 2122; do
cal 12 $y | tail +3 | cut -c1-2 | grep -Fq 25 && echo 25 Dec $y
y=`expr $y + 1`
done
Running this script with OpenBSD, the output is identical to the C# program. OpenBSD cal accepts any year from 1 to 9999, so 2008 to 2122 is well within range.
[edit] With zsh
zmodload zsh/datetime
for (( year = 2010; year <= 2121; year++ ));
if [[ $(strftime '%A' $(strftime -r '%F' $year-12-25)) == Sunday ]] print $year
If the system has 32-bit time, this script will malfunction for years >= 2038; it will print no year from 2038 to 2121 (unless today is Sunday, then it prints every year from 2038 to 2121). This happens because strftime -r '%F' $year-12-25 yields -1 for an out-of-range date, and strftime '%A' -1 yields name of today.
[edit] Ursala
A standard library, stt, provides basic date manipulation functions,
and is imported in this example. Unix era times denominated in seconds since
1969 (excluding leap seconds) are represented as natural numbers with
unlimited precision. Results are valid for the arbitrarily distant
future assuming the Gregorian calendar remains in effect.
The algorithm relies on the string_to_time function converting a date
expressed as a character string to seconds without needing a weekday field in
the input, and the time_to_string function outputting the corresponding
date with the weekday included. The output is then filtered for Sundays.
#import std
#import nat
#import stt
christmases = time_to_string* string_to_time*TS 'Dec 25 0:0:0 '-*@hS %nP* nrange/2008 2121
#show+
sunday_years = ~&zS sep` * =]'Sun'*~ christmases
output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] Vedit macro language
Buf_Switch(Buf_Free)
for (#3 = 2008; #3 < 2122; #3++) {
Reg_Set(10, "12/25/")
Num_Str(#3, 10, LEFT+APPEND)
if (JDate(@10) % 7 == 0) {
Num_Ins(#3, NOCR)
}
}
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
[edit] XPL0
The original routine in the library only worked correctly between the years 1980 and 2099. It was upgraded with this new routine that handles all dates in the Gregorian calendar, from 1583 onward. It's based on Zeller's Congruence.
include c:\cxpl\codes; \intrinsic 'code' declarations
proc WeekDay(Year, Month, Day); \Return day of week (0=Sat 1=Sun..6=Fri)
int Year, Month, Day;
[if Month<=2 then [Month:= Month+12; Year:= Year-1];
return rem((Day + (Month+1)*26/10 + Year + Year/4 + Year/100*6 + Year/400) / 7);
]; \WeekDay
int Year;
[for Year:= 2008 to 2121 do
if WeekDay(Year, 12, 25) = 1 then \25th of December is a Sunday
[IntOut(0, Year); CrLf(0)];
]
Output:
2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118
- Programming Tasks
- Solutions by Programming Task
- ABAP
- Ada
- ALGOL 68
- AppleScript
- AutoHotkey
- AutoIt
- AWK
- BBC BASIC
- Bc
- C
- C++
- C sharp
- Clojure
- CoffeeScript
- ColdFusion
- Common Lisp
- D
- Delphi
- Euphoria
- Factor
- Forth
- Fortran
- GAP
- Go
- Groovy
- Haskell
- HicEst
- Icon
- Unicon
- Icon Programming Library
- J
- Java
- JavaScript
- K
- Liberty BASIC
- Lua
- M4
- Mathematica
- MATLAB
- Octave
- Maxima
- Modula-3
- MUMPS
- VA Kernel
- NetRexx
- Objective-C
- OCaml
- OCaml Calendar Library
- Pascal
- Perl
- Perl 6
- PHP
- PicoLisp
- Pike
- PL/I
- PowerShell
- Protium
- PureBasic
- Python
- R
- REBOL
- REXX
- Ruby
- Run BASIC
- SAS
- Scala
- Scheme
- Seed7
- Smalltalk
- Suneido
- Tcl
- TI-83 BASIC
- TUSCRIPT
- UNIX Shell
- UnixPipes
- Ursala
- Vedit macro language
- XPL0
- GUISS/Omit
- ML/I/Omit
- PARI/GP/Omit
- Date and time