#!/bin/sh # next line restarts with tclsh \ exec tclsh $0 ${1+"[email protected]"} # # Author: Mark Oakden http://wiki.tcl.tk/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 [1] 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 [2] 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):

variable | german | english 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 |

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