Calendar science

This year Christmas Eve is a Sunday

Can anyone write a script to determine the years in which Christmas Eve falls on a Sunday?

3 Likes

The Bing bot provided this Python script. It seems to work for me.

import datetime

for year in range(1900, 2101):
    christmas_eve = datetime.date(year, 12, 24)
    if christmas_eve.weekday() == 6:
        print(year)
3 Likes

Seems us scriptwriters have been redunded by AI

2 Likes

Here is a bash script that determines the years in which Christmas Eve falls on a Sunday:

#!/bin/bash

for year in {1901ā€¦2099}
do
if [[ $(date -d ā€œ${year}-12-24ā€ +%A) == ā€œSundayā€ ]]
then
echo ā€œ$yearā€
fi
done

This script uses the date command to check the day of the week for December 24th of each year between 1901 and 2099. If the day is Sunday, the year is printed to the console. You can modify the range of years by changing the values in the curly braces. Itā€™s also provided by Bing AI Chat.

5 Likes

Thanks. For me, bash script is easier to understand than python.
Both python and bash versions use a ā€˜dateā€™ function.
Is anyone keen enough to understand the calendar maths
and do it from scratch?

1 Like

Does this still work based on system date on mac and pc given that there is a confusion between them about the year 1900 and 1904 being a leap year or not.
Not important for me, just remember when using excel date on the 2 systems can give different results.

1900 is not a leap year

"The rule is that if the year is divisible by 100 and not divisible by 400, leap year is skipped. "

But what is this about 1904? That should be a normal
leap year

1 Like

During my time at apple we had a great discussion regarding date differences from mac to pc and who was correct about 1900 and 1904 as excel on the two products gave different results

I cannot find the original article but this link covers most of it

Yes know the calculation for leap years
To be a leap year, the year number must be divisible by four ā€“ except for end-of-century years, which must be divisible by 400. This means that the year 2000 was a leap year, although 1900 was not.

2024, 2028, 2032 and 2036 are all leap years.

1 Like

I get it, Msoft took a shortcut to help machines with limited
calculating power. ā€¦ and it came back to haunt them.
I hope it is fixed today.

Maybe sometime over the long holiday weekend I can try to cook up a BASIC version without the aid of Bingbot. :slight_smile:

3 Likes

The only ā€œY2K bugā€ I found - post-mortem - was a developer assumed that 2000 was not a leap year, thus only 28 days in February 2000, when 29/02/2000 rolled around it caused havoc in my customerā€™s ā€œbespokeā€ mortgage management system :smiley: ā€¦

Fortunately for them (the customer) the developer was available to re-write his shonky codeā€¦ He was a half decent bloke, but still billed them for the ā€œre-writeā€ :smiley: (Iā€™d probably have done the same - they [customer] were very laccadaisical in their specification design document).

Canā€™t remember what the programming language was - I think Visual Basic. Backend was SQL Server - which was my involvement - yeah - I used to do Windows stuff on SQL Serverā€¦ Iā€™d done a bit with Sybase (which Microsoft paid to have ported to Windows NT - thatā€™s how we got SQL Server) before. Unfortunately - was never able to cross-skill in Oracle RDBMS where all the $$$ in consulting is locatedā€¦

2 Likes

So much talk about no room for all the planes that could not fly due to the y2k bug. I was working in a hospital IT department at that time and the lead up to it was massive. In the end no big deal, i even went on call for that night but nothing.

I am starting to prepare for the next big deal of 9999 but guess may not see it.

4 Likes

Here is a Powershell version I came up with myself.

$c = 0
$s = @()
for ($y = 1900; $y -le 2101; $y++) {
    $d = 358
    if ($y % 4 -eq 0) {
        $d = 359
    }
    if ($y % 100 -eq 0) {
        $d = 358
    }
    if ($y % 400 -eq 0) {
        $d = 359
    }
    $c = $c + $d
    $w = $c % 7
    if ($w -eq 0) {
        $s += [PSCustomObject]@{
            Year = $y
            Day = $d
            Weekday = $w
        }
    }
}
$s | Format-Table -AutoSize

For each year from 1900 through 2101 it decides if it is a leap year or not. Christmas Eve is either day 358 or 359 of the year. Then the running total of the number of days since 1/1/1900 is used to calculate the remainder of the cumulative days divided by 7. That gives the day of the week. If the day of the week is 0 it is Sunday. Those days are added to a PSCustomObject and displayed in a table at the end.

I checked the 28 years listed in the output against https://www.timeanddate.com and those years are correct. There may be other years that are not listed but did fall on a Sunday. Maybe someone could come up with a proof, but I trust it. It does match the output from the earlier Python script.

3 Likes

I shall run itā€¦ not in Powershellā€¦ it should go in csh or sh
The algorithm seems reasonableā€¦ you just count your way up from a known base.

2 Likes

Well before 9999, thereā€™s the UNIX 2038 date bugā€¦
Year 2038 problem - Wikipedia.

I will be 76 in 2038 - if I make it that far (my Tripp great great grandfather, a convict, lived into his 80ā€™s but since then all his Tripp male descendants barely get to, or past 65 - e.g. my dad died two months before his 67th birthday)ā€¦

I was working in a hospital IT department, leading up to Y2K - but left in early 1999 - we (my boss) hired several contractors just to do Y2K testingā€¦

I went to another ā€œhealth relatedā€ environment, mostly SCO UNIX running across West Australiaā€™s regional centres (WA regional hospitals ran much of their stuff, back then, on Progress ā€œflat fileā€ database systems hosted on SCO Openserver - and many users connected via dumb ascii terminals over serial lines to Stallion ā€œpaddle boardsā€).

One morning I came into the office**, and thereā€™d been a power outage, which the UPS didnā€™t ā€œweatherā€ā€¦ I noticed a couple of the systems in the ā€œlab / server roomā€ had the wrong date - so I set them to the correct date - only to learn - that was deliberate - they had the wrong date 'cause they were using them to test Y2K rollover! One was SCO OpenServer on a Pentium Pro server, the other one was SunOS 4x on Sun hardware - both to run these ghastly Progress RDBMS applications (I donā€™t think it was an IPX, probably an SS5 or SS4 maybe? I just looked at the price for an NVRAM battery to I can fire up my SparcStation IPX - $200 USD for a wonky little battery??? No! I guess I will continue to consider it a doorstop or monitor stand).

** the only thing I miss about that job - I HAD MY OWN OFFICE just for ME with a door! Thatā€™s the ONLY time Iā€™ve ever had that luxury!

3 Likes

I tried it in bash.
Required some considerable modification, since the way bash handles arithmetic
is arcane, to say the least.
My rough bash version

#!/bin/bash
# sunday christmas eve
c=0;
 for y in $@ 
  do d=358;
      if (( $y % 4 == 0 )); then
          d=359
      fi
      if (( $y % 100 == 0 )) then
          d=358
      fi
      if (( $y % 400 == 0 )) then
          d=359
      fi
      c=`expr $c + $d`
      w=`expr $c % 7`
      if (( $w == 0 )) then
        echo $y; echo $d; echo $w;
      fi
  done

It does not do the years loop. You can achieve that with

$ ./sunday `seq -s " " 1900  2100` >out

I get 28 years, including 2023 , so I guess it is correct.

Note:
If anyone wants to try numerical calculations in a bash script, have a look at
@abhishek 's excellent bash tutorial

You need examples.

There is an algorithm invented by Gauss which calculates ā€˜day of weekā€™ for any
nominal date. It is in Wikipedia

It does not count from a known base, but it uses modulus in the same way that you do.
You are in good company.

4 Likes

There are some quite sophisticated algorithms for determining day of the week from date.
Here is one coded in R

function(y, m, d )
# dayofweek(y,m,d)
# Sakamoto's algorithm for day of week
# 1 <= m <= 12 , y > 1752 (in UK)
# returns 0=Sunday, 1=Monday, ...
{
  t <- c(0,3,2,5,0,3,5,1,4,6,2,4)
  if (m < 3) {
    y <- y - 1
  }
  return (as.integer((y + y/4 - y/100 + y/400 + t[m] + d) %% 7))
}

We can use it to look at which Christmas Eveā€™s are Sundays by writing a simple calling function

function(y)
# cesunday() Years in which Christmas Eve is on a Sunday
{
  for(i in 1:length(y)) {
   if(dayofweek(y[i],12,24) == 0) {
    print(y[i])
   }
  }
}

and we can run it like this

> cesunday(seq(1900,2025))
[1] 1905
[1] 1910
[1] 1916
[1] 1927
[1] 1933
[1] 1944
[1] 1950
[1] 1955
[1] 1961
[1] 1967
[1] 1972
[1] 1978
[1] 1989
[1] 1995
[1] 2000
[1] 2006
[1] 2012
[1] 2017
[1] 2023

which seems to be correct.

3 Likes

Its the first time i have come across the 2038 issueā€¦ do you think 32 bit systems will still be around then

As i will be 80 at that point not sure i need to worry too much perfer to think of the feast of end of life windows 10 later this year and how much i may make, thanks microsoft for printing money for people like myself

1 Like

The interval between years with Christmas Eve on a Sunday
seems to vary between 5 and 11 years.
Can anyone explain why it is restricted to that range of
numbers?
Or is it?.. better look at a wider range of years.

I checked from 1800 to 2200 and the min is 5 and max is 12. Same for years 1000 to 3000. The calculation may not be completely valid for extremely past or future dates.

Interesting question.

Iā€™m guessing that each year it basically moves by one day, but then leap year messes it up and may skip Sunday once every so often. Thatā€™s why it is 11 or 12 maybe. From that line of thinking it should max out at 13. If it just missed it one year and then skips it in 7 that would be 13 I think.

1 Like