Linux 'cal' and 'ncal' commands and Easter

Have you used cal command
It prints a calendar, like this

$ cal
     April 2025       
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           

If you look at the man page there are various options, eg to display all months of the year, to display any year, and to user Julian day numbers.

The aspect I am interested in is ncal, which prints the calendar in column format

$ ncal
    April 2025        
Su     6 13 20 27   
Mo     7 14 21 28   
Tu  1  8 15 22 29   
We  2  9 16 23 30   
Th  3 10 17 24      
Fr  4 11 18 25      
Sa  5 12 19 26      

but what I am looking for is the -e and -o options which print the date of Easter… -e prints the date of Western Easter, -o prints the date of Eastern Orthodox Easter. These options only work with ncal

nevj@trinity:~
$ ncal -e
20/04/25
nevj@trinity:~
$ ncal -o
20/04/25

Yes, this year Easter and Orthodox Easter are the same date.

Now, here is a challenge… who can calculate in which year Easter and Orthodox Easter will again occur on the same date?

Hint: might be a good exercise for a Python script

7 Likes

I use cal and ncal all the time - it’s so convenient - considering a spend a lot of time in a terminal…

I posted something some time ago - an annoyance - Ubuntu doesn’t install ncal (the ncal deb also has “cal” and in most cases “cal” is a symlink to “ncal” anyway) by default. Why? It’s tiny, ~70 kb… What did they save by excluding it from a default install?

Also - I think later versions of Debian (like bookworm) don’t install as a default - so maybe Ubuntu inherited that behaviour from Debian? For me - “cal” is as ubiquitious as date, ls, find, sed, awk, grep et cetera…

7 Likes

MX installs cal by default, so I think Debian would

Ah yeah… but you are a real Unix user
I bet lots of Linux people dont even know it exists

1 Like

Quite possibly - I’m using Raspbian Debian Bookworm as an example, I had to install ncal after I flashed the O/S onto storage…

I haven’t tried vanilla x86_64 Debian for some time now…

I kinda went off Debian, because I kinda hate all the free, and non-free stuff - like having to hunt down a DEB file for my WiFi chipset - put it onto a thumb drive, and point the Debian installer to that location… Things may have changed… I remember there were “non-free” spins of Debian around some time ago…

5 Likes

I never had any issues with that in Devuan… that is my only hard install.

1 Like

Why should they, when they have a calendar in their shiny UI? :smile:

3 Likes

How do we pipe the output of a UI to another command?

1 Like

@nevj and all:

Hi all, :waving_hand:

I´m not quite there yet, Neville. :wink:

I know this is not the answer you were looking for.
It´s just on a sidenote and may rather be considered as some additional info:

gcal is not bad either for displaying the Easter date.

Its commands are highly configurable.
So the following is just an example for my region (Germany, state of Baden-WĂĽrttemberg):

gcal --with-week-number --cc-holidays=DE_BW -n --christian-holidays --astronomical-holidays -s 1 --time-offset=+2: april

April 2025

Montag           7 14 21 28   
Dienstag      1  8 15 22 29   
Mittwoch      2  9 16 23 30   
Donnerstag    3 10 17 24      
Freitag       4 11 18 25      
Samstag       5 12 19 26      
Sonntag       6 13 20 27      

Woche        14 15 16 17 18   

Ewige Feiertagsliste:

Erster April (DE_BW)                     - Di,   1 Apr 2025 =  -17 Tage
Zunehmender Halbmond 04.14 (Ast)         - Sa,   5 Apr 2025 =  -13 Tage
Passionssonntag (Chr)                    - So,   6 Apr 2025 =  -12 Tage
Palmsonntag (Chr)                        - So,  13 Apr 2025 =   -5 Tage  # Palm Sunday
Vollmond 02.22 (Ast)                     - So,  13 Apr 2025 =   -5 Tage
Karfreitag (Chr)                         - Fr,  18 Apr 2025  # Good Friday
Karfreitag (DE_BW)                       + Fr,  18 Apr 2025  # Good Friday
Karsamstag/Ostervorabend (Chr)           - Sa,  19 Apr 2025 =   +1 Tag  # Holy Saturday
Ostersonntag (Chr)                       - So,  20 Apr 2025 =   +2 Tage
Ostersonntag (DE_BW)                     + So,  20 Apr 2025 =   +2 Tage
Abnehmender Halbmond 03.35 (Ast)         - Mo,  21 Apr 2025 =   +3 Tage
Ostermontag (Chr)                        - Mo,  21 Apr 2025 =   +3 Tage  # Easter Sunday
Ostermontag (DE_BW)                      + Mo,  21 Apr 2025 =   +3 Tage  # Easter Monday
Neumond 21.31 (Ast)                      - So,  27 Apr 2025 =   +9 Tage
Walpurgisnacht (DE_BW)                   - Mi,  30 Apr 2025 =  +12 Tage

Here you can find and incredible source of information for gcal:

Happy Easter and many greetings to all :shortcake: :face_blowing_a_kiss:.

Rosika :slightly_smiling_face:

7 Likes

No problem, use xclip. :wink:

3 Likes

I learnt something today

5 Likes

This is nice.

I’ll use it in a tweet :slight_smile:

5 Likes

One of my favorite tools. Among other things, I use it for fetching a list of dates from a website and transforming the clipped content into an importable ICS-calendar file.

5 Likes

Thanks @Rosika - I didn’t know about gcal…

I use xclip to download stuff with yt-dlp - i.e. I copy the stream URL - then run a script that uses xclip to download the stream from the URL to a specific folder with YYYYMMDD depending on what year and month I run my script…

It works quite well…

and happy equinox or solstice or whatever Easter is… it would be hypocritical of me, being a lifelong atheist to mention religious stuff…

3 Likes

Hi Rosika,
I struggled to get there with a bash script

#!/bin/bash
for i in `seq 2025 2100`
 do 
   j=`ncal -e $i `
   k=`ncal -o $i `
#    reverse the dates  and change / to -
   jrev=`awk -F'/' '{printf("%04d-%02d-%02d\n",20$3,$2,$1)}' <<< $j`
   krev=`awk -F'/' '{printf("%04d-%02d-%02d\n",20$3,$2,$1)}' <<< $k`
#    convert dates to numbers of days since first epoch
   jval=$(date -d"$jrev" +"%s")
   kval=$(date -d"$krev" +"%s")
#    compare the numbers
   if [ $kval -eq $jval ]
    then
      echo $i
   fi
 done

I am sure someone can do better than that
Here is the result

$ ./easter.sh
2025
2028
2031
2034
2037
2038
2041
2045
2048
2052
2055
2058
2061
2069
2071
2072
2075
2079
2082
2085
2091
2095
2096
2099

So the Western and Orthodox Easters coincide quite often.
Surely someone can find an elegant way of doing this?

4 Likes

I find your method quite elegant enough. Keep it smart and simple. :+1:

3 Likes

If you saw the many failed attempts you would laugh… I am not a scripting guru.
and
It is not rugged… that awk script prepends 20 to the year… so it fails at 2100.

3 Likes

@nevj :

Hi Neville, :waving_hand:

But in the end you got the correct results.
Your script works as desired. Great! Congratulations, Neville. :+1: :1st_place_medal:

@daniel.m.tripp :

You´re welcome, Dan. I´m glad you may find it interesting.

Cheers from Rosika :slightly_smiling_face:

3 Likes

Hi Neville, :waving_hand:

O.K., I have to be honest. This one is intriguing, to say the least. :blush:
I´m just beginning to learn Python, so I couldn´t wait until I´m ready to tackle the task by myself (if ever).

So I asked ChatGPT for help. It said it could be done.

Prerequisites:

  • We’ll use two Python libraries:

    dateutil.easter for Western Easter
    orthodox_easter from the orthodox package for Orthodox Easter

  • I myself would need to install
    pip3 install orthodox
    Everything else is already present on my system

The easter_check.py would look like this:

from dateutil.easter import easter
from orthodox.easter import orthodox_easter

# Define the range of years to check
start_year = 2025
end_year = 2100

print("Years when Western and Orthodox Easter fall on the same date:\n")

for year in range(start_year, end_year + 1):
    western = easter(year)
    orthodox = orthodox_easter(year)
    
    if western == orthodox:
        print(f"{year}: Easter = {western.strftime('%d/%m/%Y')}")

If the Western and Orthodox Easter dates match for a certain year, you should be able to see a line like this printed:

2043: Easter = 05/04/2043

I haven´t tried it out myself yet.
But I certainly learned a lot by this as far a Python scripting is concerned.

You might want to give it a try? :blush:

Many greetings from Rosika :slightly_smiling_face:

2 Likes

OMG, I see… :smile:

2 Likes

Hi Rosika,
I certainly will give it a try.
It looks neater than my messy bash script. Well done.
Keep going with Python

My first attempt failed

$ python3 easter_check.py
Traceback (most recent call last):
  File "/home/nevj/easter_check.py", line 2, in <module>
    from orthodox.easter import orthodox_easter
ModuleNotFoundError: No module named 'orthodox'

I think there is something missing from my Python environment.
My Python learning curve starts here.
Update:
It seems it is a Python2 vs Python3 problem.
Your ChatGPT info is , I think Python2
The Python3 equivalent is here

so I modified your code accordingly

from dateutil.easter import easter

# Define the range of years to check
start_year = 2025
end_year = 2100

print("Years when Western and Orthodox Easter fall on the same date:\n")

for year in range(start_year, end_year + 1):
    western = easter(year,method=3)
    orthodox = easter(year,method=2)
    
    if western == orthodox:
        print(f"{year}: Easter = {western.strftime('%d/%m/%Y')}")

Now it works

$ python3 easter_check.py
Years when Western and Orthodox Easter fall on the same date:

2025: Easter = 20/04/2025
2028: Easter = 16/04/2028
2031: Easter = 13/04/2031
2034: Easter = 09/04/2034
2037: Easter = 05/04/2037
2038: Easter = 25/04/2038
2041: Easter = 21/04/2041
2045: Easter = 09/04/2045
2048: Easter = 05/04/2048
2052: Easter = 21/04/2052
2055: Easter = 18/04/2055
2058: Easter = 14/04/2058
2061: Easter = 10/04/2061
2069: Easter = 14/04/2069
2071: Easter = 19/04/2071
2072: Easter = 10/04/2072
2075: Easter = 07/04/2075
2079: Easter = 23/04/2079
2082: Easter = 19/04/2082
2085: Easter = 15/04/2085
2091: Easter = 08/04/2091
2095: Easter = 24/04/2095
2096: Easter = 15/04/2096
2099: Easter = 12/04/2099

The same result as my messy script.
It looks like Python handles dates better than bash

Maybe the Python experts can help us with this

  • how do I look up which package supplies a given function
  • is there a list of Python libraries with a summary of their content
  • where is the information on how to use the functions in a given library

So Rosika, do you have Python2 or Python3?
That would seem to be critical.

Regards
Neville

Update:
My Devuan is Python2
I tried that


nevj@trinity:~$ python
Python 2.7.18 (default, Sep 19 2023, 07:10:59) 
[GCC 10.2.1 20210110] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from dateutil.easter import easter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named dateutil.easter

So, no it is not a Python2 issue… my bad guess.

3 Likes