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).

Task
Day of the week
You are encouraged to solve this task according to the task description, using any language you may know.

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.

Ada

<lang 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;</lang> 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

ALGOL 68

Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386

<lang algol68>main:(

  1. 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
 );
 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)

)</lang> Output: <lang algol68>December 25th is a Sunday in: 2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118</lang>

AutoHotkey

<lang autohotkey>year = 2008 stop = 2121

While year <= stop {

FormatTime, day,% year 1225, dddd
If day = Sunday
 out .= year "`n"
year++

} MsgBox,% out</lang>

AutoIt

<lang 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</lang>

C

<lang c>#include <stdio.h>

  1. include <time.h>
  2. include <string.h>

int main() {

 struct tm mytime;
 int i;
 time_t m;
 
 for(i=2008; i<=2121; i++)
 {
   memset(&mytime, 0, sizeof(struct tm));
   mytime.tm_mday = 25;
   mytime.tm_mon = 11;
   mytime.tm_year = i-1900;
   m = mktime(&mytime);
   if ( m < 0 ) {
      printf("%d is the last year we can specify\n", i-1);
      break;
   }
   if ( mytime.tm_wday == 0 )
   {
     printf("25 December %d is Sunday\n", i);
   }
 }

}</lang>

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

C++

<lang cpp>#include <boost/date_time/gregorian/gregorian.hpp>

  1. 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 ;

}</lang> 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

C#

<lang csharp>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"));
           }
       }
   }

}</lang>

Using LINQ:

<lang csharp>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);
   }

}</lang>

This looks better:

<lang csharp>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);
   }

}</lang>

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

Clojure

Utilizing Java interop

<lang clojure> (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) </lang>

(2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118)


ColdFusion

<lang 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>
</cfif>

</cfloop> </lang>

Common Lisp

<lang 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)</lang>

D

I'm sure this can be done better. If anyone wants to take the time, please improve it. <lang d>import std.date; import std.stdio; void main() {

 for(long year = 2008;year<=2121;year++)
   if (0 == WeekDay(parse("December 25, "~std.string.toString(year))))
     writefln("Christmas comes on a sunday in %d",year);

}</lang>

Factor

<lang factor>2008 2121 [a,b] [ 12 25 <date> sunday? ] filter .</lang>

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. <lang forth>\ 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</lang>

Fortran

Works with: Fortran version 90 and later

Based on Forth example <lang fortran>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</lang> 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

Groovy

Solution: <lang groovy>def yuletide = { start, stop -> (start..stop).findAll { Date.parse("yyyy-MM-dd", "${it}-12-25").format("EEE") == "Sun" } }</lang>

Test program: <lang groovy>println yuletide(2008, 2121)</lang>

Output:

[2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118]

Haskell

Using the time library: <lang haskell>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]</lang>

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: <lang haskell>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]</lang>

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)

J

<lang j> load 'dates' NB. provides verb 'weekday'

  SunDec25=: #~ 0&=@:weekday@:(|:@,: ,. 12 25$~#,2:) 
  SunDec25 2008 + i.114

2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118</lang>

Java

<lang 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()); } } } }</lang> 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

JavaScript

<lang javascript>for (var year = 2008; year <= 2121; year++) {

   var yule = new Date(year, 11, 25);
   if (yule.getDay() == 0)
       try { 
           WScript.Echo(yule);  // WSH
       } catch(err) { 
           print(yule);  // Rhino
       }

}</lang> output:

Sun Dec 25 00:00:00 EST 2011
Sun Dec 25 00:00:00 EST 2016
Sun Dec 25 00:00:00 EST 2022
Sun Dec 25 00:00:00 EST 2033
Sun Dec 25 00:00:00 EST 2039
Sun Dec 25 00:00:00 EST 2044
Sun Dec 25 00:00:00 EST 2050
Sun Dec 25 00:00:00 EST 2061
Sun Dec 25 00:00:00 EST 2067
Sun Dec 25 00:00:00 EST 2072
Sun Dec 25 00:00:00 EST 2078
Sun Dec 25 00:00:00 EST 2089
Sun Dec 25 00:00:00 EST 2095
Sun Dec 25 00:00:00 EST 2101
Sun Dec 25 00:00:00 EST 2107
Sun Dec 25 00:00:00 EST 2112
Sun Dec 25 00:00:00 EST 2118

Lua

Library: LuaDate

<lang Lua>require("date")

for year=2008,2121 do

  d = date(year, 12, 25)
  if (d:getweekday() == 1) then
     print(year)
  end

end</lang>

Output:

2011
2016
2022
2033
2039
2044
2050
2061
2067
2072
2078
2089
2095
2101
2107
2112
2118

M4

<lang 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 ')')</lang>

Output:

2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112
2118

Mathematica

<lang Mathematica>Reap[If[DateString[{#,12,25},"DayName"]=="Sunday",Sow[#]]&/@Range[2008,2121]]2,1</lang> gives back: <lang Mathematica>{2011,2016,2022,2033,2039,2044,2050,2061,2067,2072,2078,2089,2095,2101,2107,2112,2118}</lang>

Modula-3

Translation of: C

Modula-3 represents time using a (safe) wrapper around the C time interface. Consequently, it suffers from the same problem as C.

<lang modula3>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.</lang>

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

Objective-C

Works with: GNUstep

It should works also with Cocoa and OpenStep in general, but I can't test these.

<lang objc>#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;

}</lang>

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

OCaml

Translation of: C

<lang 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 _ -> ()</lang>

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

Perl

<lang 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;</lang>

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: <lang perl>#! /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;</lang> or shorter: <lang perl>#! /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;</lang> 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): <lang perl>#! /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;</lang> Output:

2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118

PHP

<lang 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";
 }

} ?></lang>

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

PicoLisp

<lang PicoLisp>(for (Y 2008 (>= 2121 Y) (inc Y))

  (when (= "Sunday" (day (date Y 12 25)))
     (printsp Y) ) )</lang>

Output:

2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118

PL/I

<lang 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; </lang>

PowerShell

<lang powershell>2008..2121 | Where-Object { ([DateTime] "$_-12-25").DayOfWeek -eq "Sunday" }</lang>

PureBasic

PureBasic's internal Date() is limited between 1970-01-01 00:00:00 and 2038-01-19 03:14:07 <lang PureBasic>For i=2008 To 2037

 If DayOfWeek(Date(i,12,25,0,0,0))=0
   PrintN(Str(i))
 EndIf

Next</lang>

Python

<lang python>import datetime

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()</lang>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

R

<lang R>years <- 2008:2121 xmas <- as.POSIXlt(paste(years, '/12/25', sep="")) years[xmas$wday==0]</lang>

2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118

REBOL

<lang 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 ""]] ]</lang>

Output:

2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118

REXX

<lang rexx>do year = 2008 to 2121

   if date('w', year'1225', 's') = 'Sunday' then say year

end</lang>

Alternative: <lang rexx>do year = 2008 to 2121

   if date('b', year'1225', 's') // 7 = 6 then say year

end</lang>

Output from either:

2011
2016
2022
2033
2039
2044
2050
2061
2067
2072
2078
2089
2095
2101
2107
2112
2118

Ruby

<lang ruby>require 'date'

SUNDAY = 0

for year in 2008..2121

   day = Date.new(year, 12, 25)
   if day.wday == SUNDAY
       puts '25 Dec %d' % year
   end

end</lang> 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: <lang ruby>SUNDAY = 0

for year in 2008..2121

   begin
       day = Time.local(year, 12, 25)
       if day.wday == SUNDAY
           puts '25 Dec %d' % year
       end
   rescue ArgumentError
       puts '%d is the last year we can specify' % (year-1)
       break
   end

end</lang> 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

Smalltalk

<lang smalltalk>2008 to: 2121 do: [ :year | |date|

    date := Date newDay: 25 monthIndex: 12 year: year.
    date dayName = #Sunday
      ifTrue: [ date displayNl ]

]</lang>

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

Suneido

<lang Suneido>year = 2008 while (year <= 2121)

   {
   if Date('#' $ year $ '1225').WeekDay() is 0
       Print(year)
   ++year
   }</lang>

Output:

2011
2016
2022
2033
2039
2044
2050
2061
2067
2072
2078
2089
2095
2101
2107
2112
2118

Tcl

Works with: Tcl version 8.5

<lang 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"
   }

}</lang> 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

TI-83 BASIC

Works with TI-84+/SE only <lang ti83b>

For(A, 2008,2121
dayofWk(A,12,25
If Ans=1
Disp A
End

</lang> outputs

2011
2016
2022
2033
2039
2044
2050
2061
2067
2072
2078
2089
2095
2101
2107
2112
2118
Done

UNIX Shell

Works with: bash

<lang bash>#! /bin/bash

for i in `seq 2008 2121` do

date -d "$i-12-25" |grep Sun

done

exit 0</lang>

The first lines of output (from a 32bit GNU/Linux system, date version 6.9) are

<lang bash>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'</lang>

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)

This is the same command run on RedHat Linux. <lang bash>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$</lang>

UnixPipes

Thanks to UNIX Shell implementation <lang bash>seq 2008 2121 | xargs -IYEAR -n 1 date +%c -d 'Dec 25 YEAR' | grep Sun</lang>

(Output same as UNIX Shell)

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 force.

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.

<lang Ursala>

  1. import std
  2. import nat
  3. import stt

christmases = time_to_string* string_to_time*TS 'Dec 25 0:0:0 '-*@hS %nP* nrange/2008 2121

  1. show+

sunday_years = ~&zS sep` * =]'Sun'*~ christmases </lang> output:

2011                            
2016                            
2022                            
2033                            
2039                            
2044                            
2050                            
2061                            
2067                            
2072                            
2078                            
2089                            
2095                            
2101                            
2107                            
2112
2118

Vedit macro language

<lang vedit>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)

   }

}</lang>

Output:

2011 2016 2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095 2101 2107 2112 2118