Calculating the Date of Easter

A little calculator to get the date of Easter in various years using an algorithm from the Astronomy FAQ. MNO

 #!/bin/sh
 # next line restarts with tclsh \
        exec tclsh $0 ${1+"$@"}
 #
 # Author: Mark Oakden https://wiki.tcl-lang.org/MNO
 # Version: 1.0
 #
 # calculate Easter Sunday using the algorithm given at 
 # http://www.faqs.org/faqs/astronomy/faq/part3
 #
 # assumes Gregorian calendar
 #
 proc easterdate { year } {
     #
     # G is "golden number"
     #
     set G [expr {($year % 19) + 1}]
     #
     # H is intermediate in calculating C
     #
     set H [expr {int($year / 100)}]
     #
     # C is "century term"
     #
     set C [expr {(-1 * $H) + int($H/4) + int(8*($H+11)/25)}]
     #
     # first we need the paschal full moon.
     # the following is in days before april 19 with a couple of exceptions
     #
     set rawdays [expr {((11*$G)+$C) % 30}]
     #
     # exceptions if rawdays = 0 use days=1
     # if rawdays = 1 and G >= 12 use days=2
     # else use days=rawdays
     #
     if { $rawdays == 0 } then {
        set days 1
     } elseif { $rawdays == 1 && $G >= 12} {
        set days 2
     } else {
        set days $rawdays
     }
     #
     # now find the day that this falls on:-
     #
     set apr19 [clock scan "04/19/$year 12:00"]
     # %w is week day number Sun=0 
     set pfmweekdaynum [clock format [add_days $apr19 -$days] -format "%w"]
     #
     # Easter sunday is the next Sunday _strictly_ after PFM, so
     # if pfmweekday is sunday, we want 7 days after pfm
     # if pfmweekday is monday, we want 6 days after pfm etc.
     # i.e. we want to take (7-pfmweekdaynum) days after pfm
     #
     set easterdate [add_days $apr19 [expr {-($days - 7 + $pfmweekdaynum)}]]
 
     return $easterdate
 }
 
 proc add_days {time days} {
     if {[info tclversion] < "8.5"} {
         set res [clock scan "$days days" -base $time]
     } else {
         set res [clock add $time $days days]
     }
     return $res
 }

 for { set i 1995 } { $i <= 2015 } { incr i } {
     puts "Easter Sunday in $i will be on [clock format [easterdate $i] -format {%b %d}]"
 }

PT writes: In a strange twist of fate - the very day this was posted a colleague wished to know this date for 2004. Tcl wins the day!


TFW OK, now someone with more time on their hands than me compute the Orthodox dates. Look at http://www.assa.org.au/edm.html#OrthCalculator for a clue.


Gerald Lester Put braces around expressions just like they should be.


glennj 2008-02-08 -- removed date arithmetic using 86400 seconds per day, replaced with use of proper clock math


GWM of course this only works for the period 1902-2037 (as the clock function runs out of seconds in 32 bit). Hopefully we will all be using 64 bit by then! Any hope of calculating Easter pre-1902?

NB there is an approximately 19 year cycle for the date of Easter [L1 ] try this:

  for { set i 1906 } { $i <= 2138 } { incr i 19 } {
     puts "Easter Sunday in $i will be on [clock format [easterdate $i] -format {%b %d}]"
  }

and

  for { set i 1905 } { $i <= 2138 } { incr i 19 } {
     puts "Easter Sunday in $i will be on [clock format [easterdate $i] -format {%b %d}]"
  }

and

  for { set i 1904 } { $i <= 2138 } { incr i 19 } {
     puts "Easter Sunday in $i will be on [clock format [easterdate $i] -format {%b %d}]"
  }

to see the repetition of days within 3-4 days of each other (of course these days are rounded to the nearest Sunday). This relates to the Metonic cycle of the moons orbit [L2 ] which returns to the same position very nearly every 19 years. The effect is also seen in the dates of solar eclipses (known to the Greeks).


gkubu another algorithm (doesn't need 64 bit architecture :-)

proc gregorianEasterSunday { year } {

  # returns date (ISO format yyyy-mm-dd) of Easter Sunday for the given year 
  # http://www.ptb.de/cms/fachabteilungen/abt4/fb-44/ag-441/darstellung-der-gesetzlichen-zeit/wann-ist-ostern.html

    set x $year    ;# use variable names as in "wann-ist-ostern.html"

  # k: century
    set k [ expr { $x/100 } ]                           

  # auxiliary computations
    set m [ expr { 15 + (3*$k + 3)/4 - (8*$k + 13)/25 } ]     
    set s [ expr { 2 - (3*$k + 3)/4 } ]                     
    set a [ expr { $x % 19 } ]
    set d [ expr { (19*$a + $m) % 30 } ]
    set r [ expr { $d/29 + ($d/28 - $d/29) * $a/11 } ]

  # og: date of full moon in March
    set og [ expr { 21 + $d - $r } ]

  # sz: first sunday in march
    set sz [ expr { 7 - ($x + $x/4 + $s) % 7 } ]

  # oe: intermediate
  # os: Easter Sunday (number of days counted from March 1st -> 32 = April 1st)
  # om: month (March or April) of Easter
    set oe [ expr { 7 - ($og-$sz) % 7 } ]
    set os [ expr { $og + $oe } ]
  # 'wann-ist-ostern.html' ends here - rest is my own responsibility
    set om [ expr { 3 + $os/32 } ]

  # day in month
    if { $os > 31 } {
        set os [ expr { $os - 31 } ]
    }

    return "$x-[format %02d $om]-[format %02d $os]"

}

For julian calendar dates set m = 15 and s = 0 (wikipedia information, not tested)
The variables in 'wann-ist-ostern.html' are explained as follows (sorry, don't know the english terms):

variablegermanenglish attempt
k Säkularzahl secular number
m säkulare Mondschaltung secular lunar leap (?)
s säkulare Sonnenschaltung secular solar leap (?)
a Mondparameter lunar parameter (?)
d Keim für den ersten Vollmond im Frühling seed for first full moon in spring
r kalendarische Korrekturgröße calendaric correcting quantity (?)
og Ostergrenze Easter barrier (?)
sz erster Sonntag im März first sunday in March
oe Entfernung des Ostersonntags von der Ostergrenze in Tagen distance in days between Easter Sunday and Easter barrier
os Datum des Ostersonntags als Märzdatum date of Easter Sunday as if it was in March

While trying to find translations I came across this "bag of algorithms":
http://www.merlyn.demon.co.uk/estralgs.txt
and noted by chance that the ptb page has an englisch equivalent:
http://www.ptb.de/cms/en/fachabteilungen/abt4/fb-44/ag-441/realisation-of-legal-time-in-germany/the-date-of-easter.html