GM Arts Home > Popular Science > Calendar & Easter > Easter Algorithms
Lights travels faster than sound, which is why some people seem so bright until they talk.
  Home   Home 
  Electric Guitar   Electric Guitar 
  Making Music   Making Music 
  Popular Science   Popular Science 
  Calendar & Easter   Calendar & Easter 
   Calendar History 
   About Easter Dating 
   Easter Dates 
   Easter Date FAQ 
 Easter Algorithms 
   A Perpetual Calendar 
  Einstein   Einstein's Relativity 
  Contact GM Arts   Contact GM Arts 
 
 
Site Map
 
Copyright
Notice
Easter Date Algorithms

This page is for computer programmers who wish to include Easter data calculation code in their programs. Please be aware that many shorter code segments are littered throughout the Internet. These usually have year restrictions and only calculate one type of Easter date (there are 3 types - read below). Even worse, many don't even state what their limitation are, or claim extraordinary coverage such as from 1AD to forever (this is just nonsense - the earliest valid year for any algorithm is 326 AD in the Julian calendar, and the Gregorian calendar is valid until about 4099 AD).


Calendar Overview

Algorithms on this page show different ways to calculate Easter Sunday dates. It is important to understand which method, which calendar and which year range applies to each method.

The Julian calendar applies to the original calculation method from 326 AD, which was the first year a unified Easter Dating method was used. Some methods claim to work from 1 AD, which is just plain silly - Easter was not celebrated before Christ's death, and as already stated, a unified method was not used until 326 AD. The Julian calendar had fallen out of alignment in measuring solar years (keeping months aligned with seasons) well before the Gregorian calendar was introduced. Nevertheless, the Julian calendar is still used today by Orthodox churches as the basis for their Easter.

The Gregorian calendar was first introduced in October 1582 in Italy, and has subsequently replaced the Julian calendar over following years in other countries. The last country to adopt the Gregorian calendar was Greece in 1923. This calendar is highly accurate, but will need a day adjustment in or shortly after 4100 AD. So Easter algorithms using the Gregorian calendar apply to years 1583 AD to 4099 AD.

Note that there is a new Easter Sunday date calculation that applies to the Gregorian calendar, but it was not necessarily adopted in all countries at the same time the Gregorian calendar was introduced. So you may need to do some research to determine how different countries implemented these changes. Of course, churches still using the Julian calendar simply convert their Julian Easter Sunday date to the equivalent date in the Gregorian calendar.

So there are 3 possible ways to calculate Easter date. The method depends on when the Gregorian calendar was used in the country of interest, and if applicable, when the Western calculation was implemented.

  1. Original Julian calculation with a Julian calendar date (used historically)
  2. Original Julian calculation with a Gregorian calendar date (currently used by Orthodox religions)
  3. New Gregorian calculation with a Gregorian calendar date (currently used by Western religions)

Algorithm Overview

Is there a single definitive and correct algorithm? - YES! The algorithm based on the extraordinary research by Ron Mallen is correct for all years, using either method and the appropriate calendar. Ron's research was conducted over a period of more than 20 years, and covers aspects of astronomy, calendar history and the Easter Dating methods. You can see his Easter information at the Astonomical Society of South Australia site.

What Ron has done is to condense the approx 19 tables used in the Christian prayer books that define Easter into 5 tables that allow anyone to calculate Easter with just a calculator. This has been cross-checked with known historic dates, astronomical publications, other algorithms and various scientific references. Note that he has also discovered that many encyclopaedia and almanac definitions have heavily plagiarised a wrong definition from around the mid 1970's.

I wrote the algorithm that implements these tables, and have shown it below as EasterMallen. I have reverse-engineered this algorithm to reproduce the source tables and they match exactly. It is not the shortest algorithm, but because it can be proved to be directly derived from the published definition, I am confident this method is 100% accurate.

Henk Reints has a good site showing how different algorithms work. If you use any of these, or even your algorithm, I strongly suggest you check it against EasterMallen for accuracy.


And Finally - The Code!

You can cut and paste the code below. Most code is in Visual Basic, however, there are also implementations for C, Delphi (object Pascal) Javascript (or ECMA Script) and Matlab.

To keep things well defined, I have used the following method constants in Visual Basic code below, and have included argument checking in all VB algorithms.

  • method 1 is the original calculation in the Julian calendar
  • method 2 is the original method with the date converted to the Gregorian calendar
  • method 3 is the revised method in the Gregorian calendar

This example shows how to call the procedure EasterMallen() for the year 1999 and method 3 in Visual Basic.


   'declarations (all integers)
   Const EDM_JULIAN = 1
   Const EDM_ORTHODOX = 2
   Const EDM_WESTERN = 3
   'in an event procedure ...
   Dim d       As Integer
   Dim m       As Integer
   Dim y       As Integer
   Dim method  As Integer
   'get year and method from some user input
   y = 1999
   method = EDM_WESTERN
   If EasterDate(d, m, y, method) then
   ' _ is a line continuation character
      MsgBox "Easter in " & Format$(y) & " occurs on Sunday " _
         & Format$(DateSerial(y, m, d), "Medium date"), vbInformation
   End If


Show Me The Algorithms

  • Function EasterMallen() contains comments that describe Easter and how to use the correct method. It includes argument validation, and the Julian to Gregorian conversion required for method 2. This one function does it all, and returns TRUE if valid arguments were supplied, otherwise FALSE.
  • Function EasterOudin() is Oudin's (1940) algorithm has been adapted by Claus Tondering, and further modified by me to include method 2 and validate the arguments. With these updates, this is also valid for all methods for all years in the appropriate calendars.
  • EasterGauss() is the brilliant mathematician Gauss' algorithm. It is correct for method 1 only, for all years from 326 AD.
  • EasterKershaw() was posted by Simon Kershaw. This is valid for all methods for all years in the appropriate calendars.
  • EasterHodges() is by David Hodges, derived by refining the "Butcher's Ecclesiastical Calendar" rule. Valid for method 3 (Western Easters) - the revised calculation in the Gregorian calendar from 1583 to 4099 AD.
  • GetEasterDate() written in C. I haven't checked this, however, it looks right. This was generously provided to me by email.
  • GetEasterDate() written in Delphi. Also not checked but looks right, and generously provided to me by Thomas Koehler.
  • A Javascript (or ECMA Script) implementation of the Easter calculations.
  • GetEasterDate() written in Matlab. Also not checked but looks right, and generously emailed to me by Justin Solms.

  In Visual Basic - long, but accurate for all years and all methods in the appropriate calendar.

Function EasterMallen (d, m, ByVal y, ByVal method) As Boolean


' EASTER SUNDAY DATE CALCULATION
' This procedure returns Easter Sunday day and month
' for a specified year and method.
' Inputs:
' y is the specified year
' method is 1, 2 or 3 as detailed below
' Outputs:
' d & m are the returned day and month
' Procedure Calls:
' Function ValidateArgs()
' Sub GetEasterDate()
'====================================================
' The Gregorian calendar has gradually been adopted world
' wide over from October 1582.  The last known use of the
' Julian calendar by the author was in Greece in 1923.
' Either at the time of the calendar change or at a later
' date, some (but not all) regions have used a revised
' Easter date calculation based on the Gregorian calendar.
' The Gregorian calendar is valid until 4099.
' As a result, the 3 possible methods are:
' 1. The original calculation based on the Julian calendar
' 2. The original calculation, with the Julian date
'    converted to the equivalent Gregorian date
' 3. The revised calculation based on the Gregorian calendar
' Most Western churches moved from method 1 to method 3 at
' the adoption of the Gregorian calendar, while most
' Orthodox churches moved from method 1 to method 2.
' Here is a guide on which method to use.  It is important
' check the history of the region in question to find the
' correct date of their change from Julian to Gregorian
' calendars, and if applicable, their change from the
' original to revised Easter Sunday date calculation.
' AUSTRALIA
'   Has used the Gregorian calendar since settlement
'   Western churches & public holidays use method 3
'   Orthodox churches use method 2
' EUROPE
'   For years 326 to 1582, use method 1
'   What was then Italy changed calendar AND calculation
'   method in October 1582, so for years 1583 to 4099,
'   use method 3.  Most mainland European regions had
'   converted to the Gregorian calendar by 1700
' ENGLAND
'   For years 326 to 1752, use method 1
'   Adopted the Gregorian calendar in September 1752
'   Use method 3 for Western churches for years 1753 to 4099
'   Use method 2 for Orthodox churches for years 1753 to 4099
' AMERICA
'   Use method 1 from 326 AD until changes as follows:
'   Regions of America under French influence adopted the
'   Gregorian calendar in October 1582, while regions
'   under British influence adopted both the new calendar
'   and calculation from September 1752.
'   Use method 2 for Orthodox churches after the adoption
'   of the Gregorian calendar.
'   Use method 3 for Western churches after the adoption
'   of the Gregorian calendar.
'======================================================
'Method 1: ORIGINAL CALCULATION
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' From 326 AD, Easter Sunday was determined as the
' Sunday following the Paschal Full Moon (PFM) date
' for the year based on the Julian Calendar.  PFM dates
' were made up of a simple cycle of 19 Julian calendar
' dates.  This method returns a Julian calendar date,
' and applies for all years from 326
' (The author's last known use of the Julian calendar
' was in Greece in 1923).
'Method 2: ORIGINAL CALCULATION converted to GREGORIAN CALENDAR
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Same (original) calculation, also converts the Julian
' calendar date to the equivalent Gregorian calendar date.
' It applies for years 1583 to 4099.  This method
' is currently used by Orthodox Churches.
'Method 3: REVISED CALCULATION
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' This method calculates Easter Sunday as the Sunday
' following the Paschal Full Moon (PFM) date for the
' year based on the Gregorian Calendar.  PFM dates are
' calculated from the relationship between the sun,
' moon & earth (as understood in 1582) using many 19
' Gregorian calendar date cycles.   This method was
' adopted from 1583 in Europe, 1753 in England and is
' currently used by Western churches.
'================================================
' Validate arguments
' returns true if y (year) and method combination is valid
' y and method are both integers
	d = 0	    'default values for invalid arguments
	m = 0
	EasterMallen = False
	If method < 1 Or method > 3 Then
		MsgBox "Method must be 1, 2 or 3", vbExclamation
		Exit Function
	ElseIf method = 1 And y < 326 Then
		MsgBox "The original calculation applies to all years from 326 AD", vbExclamation
		Exit Function
	ElseIf (method = 2 Or method = 3) And (y < 1583 Or y > 4099) Then
		MsgBox "Gregorian calendar Easters apply for years 1583 to 4099 only", vbExclamation
		Exit Function
	Else
		EasterMallen = True
	End If
' Calculate Easter Sunday date
	Dim FirstDig, Remain19, temp    'intermediate results (all integers)
	Dim tA, tB, tC, tD, tE          'table A to E results (all integers)
	FirstDig = y \ 100              'first 2 digits of year (\ means integer division)
	Remain19 = y Mod 19             'remainder of year / 19
	If method = 1 Or method = 2 Then
  ' calculate PFM date
		tA = ((225 - 11 * Remain19) Mod 30) + 21
	' find the next Sunday
		tB = (tA - 19) Mod 7
		tC = (40 - FirstDig) Mod 7
		temp = y Mod 100
		tD = (temp + temp \ 4) Mod 7
		tE = ((20 - tB - tC - tD) Mod 7) + 1
		d = tA + tE
		If method = 2 Then  'convert Julian to Gregorian date
			'10 days were 'skipped' in the Gregorian calendar from 5-14 Oct 1582
			temp = 10
			'Only 1 in every 4 century years are leap years in the Gregorian
			'calendar (every century is a leap year in the Julian calendar)
			If y > 1600 Then temp = temp + FirstDig - 16 - ((FirstDig - 16) \ 4)
			d = d + temp
		End If
	ElseIf method = 3 Then
	' calculate PFM date
		temp = (FirstDig - 15) \ 2 + 202 - 11 * Remain19
		Select Case FirstDig
			Case 21, 24, 25, 27 To 32, 34, 35, 38
				temp = temp - 1
			Case 33, 36, 37, 39, 40
				temp = temp - 2
		End Select
		temp = temp Mod 30
		tA = temp + 21
		If temp = 29 Then tA = tA - 1
		If (temp = 28 And Remain19 > 10) Then tA = tA - 1
	' find the next Sunday
		tB = (tA - 19) Mod 7
		tC = (40 - FirstDig) Mod 4
		If tC = 3 Then tC = tC + 1
		If tC > 1 Then tC = tC + 1
		temp = y Mod 100
		tD = (temp + temp \ 4) Mod 7
		tE = ((20 - tB - tC - tD) Mod 7) + 1
		d = tA + tE
	End If
' return the date
	If d > 61 Then
		d = d - 61
		m = 5       'for method 2, Easter Sunday can occur in May
	ElseIf d > 31 Then
		d = d - 31
		m = 4
	Else
		m = 3
	End If
End Function


In Visual Basic, this is correct for all methods for all years in the appropriate calendars.

Function EasterOudin (d, m, ByVal y, ByVal method) As Boolean

'==========================================================
'This algorithm is adapted from a faq document by Claus Tondering
'URL: http://www.pip.dknet.dk/~pip10160/calendar.faq2.txt
'E-mail: c-t@pip.dknet.dk.
'The FAQ algorithm is based in part on the algorithm of Oudin (1940)
'as quoted in "Explanatory Supplement to the Astronomical Almanac",
'P. Kenneth Seidelmann, editor.
'Additions by GM Arts:
'(1) checks year and method arguments are valid
'(2) adds method 2 calculations (original calculation, converted to Gregorian date)
'(3) modified d and m calculations to account for later dates produced by method 2
'==========================================================
' Validate arguments
' returns true if y (year) and method combination is valid
' y and method are both integers
    d = 0	    'default values for invalid arguments
    m = 0
    EasterOudin = False
    If method < 1 Or method > 3 Then
        MsgBox "Method must be 1, 2 or 3", vbExclamation
        Exit Function
    ElseIf method = 1 And y < 326 Then
        MsgBox "The original calculation applies to all years from 326 AD", vbExclamation
        Exit Function
    ElseIf (method = 2 Or method = 3) And (y < 1583 Or y > 4099) Then
        MsgBox "Gregorian calendar Easters apply for years 1583 to 4099 only", vbExclamation
        Exit Function
    Else
        EasterOudin = True
    End If
Dim g   'golden year - 1
Dim c   'century
Dim h   '= (23 - Epact) mod 30
Dim i   'no of days from March 21 to Paschal Full Moon
Dim j   'weekday for PFM (0=Sunday, etc)
Dim p   'no of days from March 21 to Sunday on or before PFM
        '(-6 to 28 methods 1 & 3, to 56 for method 2)
Dim e   'extra days to add for method 2 (converting Julian date to Gregorian date)
    g = y Mod 19
    If method = 1 Or method = 2 Then 'old method
        i = (19 * g + 15) Mod 30
        j = (y + y \ 4 + i) Mod 7
        If method = 2 Then  'extra dates to convert Julian to Gregorian date
            e = 10
            If y > 1600 Then e = e + y \ 100 - 16 - (y \ 100 - 16) \ 4
        End If
    ElseIf method = 3 Then          'new method
        c = y \ 100
        h = (c - c \ 4 - (8 * c + 13) \ 25 + 19 * g + 15) Mod 30
        i = h - (h \ 28) * (1 - (h \ 28) * (29 \ (h + 1)) * ((21 - g) \ 11))
        j = (y + y \ 4 + i + 2 - c + c \ 4) Mod 7
    End If
'return day and month
    p = i - j + e
' p can be from -6 to 56 corresponding to dates 22 March to 23 May
' (later dates apply to method 2, although 23 May never actually occurs)
    d = 1 + (p + 27 + (p + 6) \ 40) Mod 31
    m = 3 + (p + 26) \ 30
End Function


This is correct for method 1, for all years from 326 AD in the Julian calendar.

Function EasterGauss(d, m, y, method) As Boolean

'returns Orthodox Easter Sundays in the Julian calendar
' Validate arguments
' returns true if y (year) and method combination is valid
' y and method are both integers
    d = 0	    'default values for invalid arguments
    m = 0
    EasterGauss = False
    If method <> 1 Then
        MsgBox "Method must be 1", vbExclamation
        Exit Function
    ElseIf y < 326 Then
        MsgBox "The original calculation applies to all years from 326 AD", vbExclamation
        Exit Function
    Else
        EasterGauss = True
    End If
Dim R1, R2, R3, R4, R5
Dim RA, RB, RC
    R1 = y Mod 19
    R2 = y Mod 4
    R3 = y Mod 7
    RA = 19 * R1 + 16
    R4 = RA Mod 30
    RB = 2 * R2 + 4 * R3 + 6 * R4
    R5 = RB Mod 7
    RC = R4 + R5
    d = RC + 21
    m = 3
    If d > 31 Then
        d = d - 31
        m = 4
    End If
End Function


Accurate for all years and all methods in the appropriate calendar.

Function EasterKershaw(d, m, ByVal y, ByVal method) As Boolean

'method posted by Simon Kershaw
'<webmaster@ely.anglican.org>
' Validate arguments
' returns true if y (year) and method combination is valid
' y and method are both integers
    d = 0	    'default values for invalid arguments
    m = 0
    EasterKershaw = False
    If method < 1 Or method > 3 Then
        MsgBox "Method must be 1, 2 or 3", vbExclamation
        Exit Function
    ElseIf method = 1 And y < 326 Then
        MsgBox "The original calculation applies to all years from 326 AD", vbExclamation
        Exit Function
    ElseIf (method = 2 Or method = 3) And (y < 1583 Or y > 4099) Then
        MsgBox "Gregorian calendar Easters apply for years 1583 to 4099 only", vbExclamation
        Exit Function
    Else
        EasterKershaw = True
    End If
Dim golden, solar, lunar, pfm, dom
    golden = (y Mod 19) + 1             'the GOLDEN number
    If method = 1 Or method = 2 Then    'original calculation
        dom = (y + (y \ 4) + 5) Mod 7                           'the DOMINICAL number - finding a Sunday
        pfm = PosMod(3 - (11 * golden) - 7, 30)                 'uncorrected date of Paschal Full Moon
    ElseIf method = 3 Then              'revised calculation
        dom = PosMod(y + (y \ 4) - (y \ 100) + (y \ 400), 7)    'the DOMINICAL number - finding a Sunday
        solar = (y - 1600) \ 100 - (y - 1600) \ 400             'solar and lunar corrections
        lunar = (((y - 1400) \ 100) * 8) \ 25
        pfm = PosMod(3 - (11 * golden) + solar - lunar, 30)     'uncorrected date of Paschal Full Moon
    End If
    If (pfm = 29) Or (pfm = 28 And golden > 11) Then pfm = pfm - 1  'corrected PFM date (days after 21 March)
    d = pfm + PosMod(4 - pfm - dom, 7) + 1                      'Easter as no of days after 21 March
    If method = 2 Then                  'convert to Gregorian calendar
        d = d + 10
        If y > 1600 Then d = d + (y \ 100) - 16 - (((y \ 100) - 16) \ 4)
    End If
    If d < 11 Then
        m = 3
        d = d + 21
    ElseIf d < 41 Then
        m = 4
        d = d - 10
    Else
        m = 5
        d = d - 40
    End If
End Function


Accurate for method 3 (Western Easters only) from 1583 to 4099 in the Gregorian calendar.

Function EasterHodges(dy, mth, ByVal y, ByVal method) As Boolean

'by David Hodges, derived by refining the "Butcher's Ecclesiastical Calendar" rule
'eliminating one step in the process
Dim a, b, c, d, e, f, g, h, j, k, m, n, p
' Validate arguments
    If method <> 3 Or y < 1583 Or y > 4099 Then
        EasterHodges = False
        d = 0
        m = 0
        MsgBox "Hodges method only applies to the revised calculation in the Gregorian calendar from 1583 to 4099 AD"
        Exit Function
    End If
    EasterHodges = True
    a = y \ 100
    b = y Mod 100
    c = (3 * (a + 25)) \ 4
    d = (3 * (a + 25)) Mod 4
    e = (8 * (a + 11)) \ 25
    f = (5 * a + b) Mod 19
    g = (19 * f + c - e) Mod 30
    h = (f + 11 * g) \ 319
    j = (60 * (5 - d) + b) \ 4
    k = (60 * (5 - d) + b) Mod 4
    m = (2 * j - k - g + h) Mod 7
    n = (g - h + m + 114) \ 31
    p = (g - h + m + 114) Mod 31
    dy = p + 1
    mth = n
'Easter Sunday is g - h + m days after March 22nd
'(the earliest possible Easter date)
End Function


C Implementation of GetEasterDate()

The author calls functions in a date class. Below are 2 functions;
   Please be aware of the following:
- The date class has 3 obvious members, but month numbers are 0-11.
- We have overloaded Date+Int to add or subtract days from a date
- GetDayOfWeek() simply returns 0 (Sunday) to 6 (Saturday)
- The line 'if(nCent>20)' is simply a performance optimization because practical use
  will be for years in this and next century.
- As you can see I have chosen a different algorithm for the Orthodox Easter. Since we
  write commercial software I preferred an algorithm that was not in a computer language.
// - The code to find the Paschal Full Moon is adapted from a
//   Visual Basic program found on www.auslink.net/~gmarts.
Date Date::RomanEasterSunday(int nYear)
{
int nCent=nYear/100;
int nRemain19=nYear%19;
 // - n1 is the number of days since 21-Mar of the PFM
int n1=(nCent-15)/2 + 202 - 11*nRemain19;
if(nCent>20)
{
  if(nCent>26)
   --n1;
  if(nCent>38)
   --n1;
  if(nCent==21 || nCent==24 || nCent==25 || nCent==33 || nCent==36 || nCent==37)
   --n1;
}
n1%=30;
if(n1==29 || (n1==28 && nRemain19>10))
  --n1;
 // - This can only be in March or April
Date dtPFM;
dtPFM.m_year=nYear;
if(n1>10)
{
  dtPFM.m_month=3;
  dtPFM.m_date=n1-10;
}
else
{
  dtPFM.m_month=2;
  dtPFM.m_date=n1+21;
}
 int nWeekDay=dtPFM.GetDayOfWeek();
 return dtPFM+(7-nWeekDay);
}
//  -This function is based off a non program based algoritm
//   described in cssa.stanford.edu/~marcos/ortheast.html.
Date Date::OrthodoxEasterSunday(int nYear)
{
int nRemain19=nYear%19;
int nRemain7=nYear%7;
int nRemain4=nYear%4;
 // - Things are a bit simpler in the Julian Calendar, this is
//   a formula by Gauss for the number of days after 21-Mar.
int n1=(19*nRemain19 + 16) % 30;
int n2=(2*nRemain4+4*nRemain7+6*n1) % 7;
int n3=n1+n2;
 // - Then convert to the Gregorian Calendar (1583 onwards)
int nCent=nYear/100;
n3+=nCent-nCent/4-2;
 // - The Orthodox Easter in the Gregorian calendar can fall in May
//   (and can not possibly fall in March anytime after year 1582).
Date dt;
dt.m_year=nYear;
if(n3>40)
{
  dt.m_month=4;
  dt.m_date=n3-40;
}
else if(n3>10)
{
  dt.m_month=3;
  dt.m_date=n3-10;
}
else
{
  dt.m_month=2;
  dt.m_date=n3+21;
}
 return dt;
}


Delphi Implementation of GetEaterDate()

procedure GetEasterDate (y, method : word; var d, m : integer);
var
   FirstDig, Remain19, temp,              {intermediate results}
   tA, tB, tC, tD, tE         : integer;  {table A to E results}
begin
(* :=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
  *  This algorithm is an arithmetic interpretation
  *  of the 3 step Easter Dating Method developed
  *  by Ron Mallen 1985, as a vast improvement on
  *  the method described in the Common Prayer Book
  *  Published Australian Almanac 1988
  *  Refer to this publication, or the Canberra Library
  *  for a clear understanding of the method used
  *  Because this algorithm is a direct translation of the
  *  official tables, it can be easily proved to be 100%
  *  correct
  *  It's free!  Please do not modify code or comments!
  *  11.7.99 - Pascal converting by Thomas Koehler, www.thkoehler.de
   :=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=*)
    FirstDig := y div 100;            {first 2 digits of year}
    Remain19 := y mod 19;             {remainder of year / 19}
    if (method = 1) or (method = 2) then
        begin
         {calculate PFM date}
        tA := ((225 - 11 * Remain19) mod 30) + 21;
         {find the next Sunday}
        tB := (tA - 19) mod 7;
        tC := (40 - FirstDig) mod 7;
        temp := y mod 100;
        tD := (temp + temp div 4) mod 7;
        tE := ((20 - tB - tC - tD) mod 7) + 1;
        d := tA + tE;
        if method = 2 then  {convert Julian to Gregorian date}
            begin
            {10 days were skipped
            in the Gregorian calendar from 5-14 Oct 1582}
            temp := 10;
            {Only 1 in every 4 century years are leap years in the Gregorian
            calendar (every century is a leap year in the Julian calendar)}
            if y > 1600 then
                temp := temp + FirstDig - 16 - ((FirstDig - 16) div 4);
            d := d + temp;
            end;
        end
    else
        begin
       {calculate PFM date}
        temp := (FirstDig - 15) div 2 + 202 - 11 * Remain19;
        if (FirstDig > 26) then temp := temp - 1;
        if (FirstDig > 38) then temp := temp - 1;
        if (FirstDig = 21) Or (FirstDig = 24) Or (FirstDig = 25)
          Or (FirstDig = 33) Or (FirstDig = 36) Or (FirstDig = 37) then
            temp := temp - 1;
        temp := temp mod 30;
        tA := temp + 21;
        if (temp = 29) then
            tA := tA - 1;
        if (temp = 28) and (Remain19 > 10) then
            tA := tA - 1;
       {find the next Sunday}
        tB := (tA - 19) mod 7;
        temp := (40 - FirstDig) mod 4;
        {//tC := temp - (temp > 1) - (temp := 3)}
        tC := temp;
        if temp > 1 then tC := tC + 1;
        if temp = 3 then tC := tC + 1;
        temp := y mod 100;
        tD := (temp + temp div 4) mod 7;
        tE := ((20 - tB - tC - tD) mod 7) + 1;
        d := tA + tE;
        end;
  {return the date}
    m := 3;
    if (d > 61) then
    begin
        d := d - 61;  {when the original calculation is converted to the}
        m := 5;       {Gregorian calendar, Easter Sunday can occur in May}
    end;
    if (d > 31) then
      begin
          d := d - 31;
          m := 4;
      end;
end;


Javascript Easter Date Calculator()
This is a basic Javascript implementation of the Easter date calculator that uses a form for input, and shows the results in a popup dialog box. You can see a working page here. For a more sophisticated dynamic HTML implementation, click here.

Here's the form HTML code:

  <form name="UserInput">
    Enter a year from 326 to 4099 AD ...
    <input name="YearEntry" type="text" value="2000">
    <input type="button" value="Show Easters" onclick="ShowEasters(UserInput.YearEntry.value)" id="button1" name="button1">
  </form>

And here's the script:

<script language="JavaScript">
<!--
// (C)opyright GM Arts 1997-1999
//  GLOBAL VARIABLES
//  ~~~~~~~~~~~~~~~~
   var jDay = 0;
   var jMonth = 0;
   var oDay = 0;
   var oMonth = 0;
   var wDay = 0;
   var wMonth = 0;
   var year = 0;
//  STARTUP CODE
//  ~~~~~~~~~~~~
// check browser is version 2 or more
   if (parseFloat(navigator.appVersion) < 2)
      alert ("You may need to upgrade your browser to reliably use the Easter Date calculator");
//  FUNCTIONS
//  ~~~~~~~~~
function ShowEasters(yr)
{
   year = parseInt(yr, 10);
   if (isNaN(year))
      year = 0;
   // reset vars
   jDay = 0;
   jMonth = 0;
   oDay = 0;
   oMonth = 0;
   wDay = 0;
   wMonth = 0;
   //get relevant Easter dates
   if ((year <= 325) || (year > 4099))
      alert("select a year from 326 to 4099");
   else {
      EasterJulian();	// used for all calculations
      if ((year > 325) && (year <= 1582)) {
         alert("Easter Sunday date for " + year + ": "
            + GetMonth(jMonth) + " " + GetOrdinal(jDay)
            + " in the Julian calendar ");
      }
      else {	// year is 1583 to 4099
         EasterOrthodox (year, jDay, jMonth);
         EasterWestern ();
         if (year <= 1923) {
            // clarify that this is a Gregorian date
            // last known use of the Julian calendar was in 1923
            alert("Easter Sunday date for " + year + ": "
               + GetMonth(wMonth) + " " + GetOrdinal(wDay)
               + ".\n\n"
               + "Orthodox Easter Sunday date for " + year + ": "
               + GetMonth(oMonth) + " " + GetOrdinal(oDay)
               + "\n(in the Gregorian calendar), which is the same day as\n"
               + GetMonth(jMonth) + " " + GetOrdinal(jDay)
               + " in the Julian calendar\n(for regions using that calender at the time).");
         }
         else {
            alert("Easter Sunday date for " + year + ": "
               + GetMonth(wMonth) + " " + GetOrdinal(wDay) + ".\n\n"
               + "Orthodox Easter Sunday date for " + year + ": "
               + GetMonth(oMonth) + " " + GetOrdinal(oDay) + ",\n"
               + "which is the same day as\n"
               + GetMonth(jMonth) + " " + GetOrdinal(jDay)
               + " in the Julian calendar (no longer in use).");
         }
      }
   }
}
function IntDiv (num, dvsr)
// performs integer division of num/dvsr - eg IntDiv(9,4)=2
{
   var negate = false;
   var result = 0;
   if (dvsr == 0)
      return null;
   else {
      if (num * dvsr < 0 )
         negate = true;
      if (num < 0)
         num = -num;
      if (dvsr < 0)
         dvsr = -dvsr;
      result = ((num - (num % dvsr)) / dvsr);
      if (negate)
         return -result;
      else
         return result;
   }
}
function GetMonth(m)
{
   //switch is better, but not supported in JavaScript ver 1.0
   if (m==3)
      return ("March");
   if (m==4)
      return ("April");
   if (m==5)
      return ("May");
}
function GetOrdinal(d)
{
   var rmdr = 0;
   rmdr = d % 10;
   if (((d >= 4) && (d <= 20)) || (rmdr == 0) || (rmdr > 3))
      return (d + "th");
   else {
      //switch is better, but not supported in JavaScript ver 1.0
      if (rmdr==1)
         return (d + "st");
      if (rmdr==2)
         return (d + "nd");
      if (rmdr==3)
         return (d + "rd");
   }
}
function EasterJulian()
{
   var g = 0;
   var i = 0;
   var j = 0;
   var p = 0;
   g = year % 19;
   i = (19 * g + 15) % 30;
   j = (year + IntDiv(year, 4) + i) % 7;
   p = i - j + 28;
   jDay = p;
   jMonth = 4;
   if (p > 31)
      jDay = p - 31;
   else
      jMonth = 3;
}
function EasterWestern()
{
   var g = 0;
   var c = 0;
   var h = 0;
   var i = 0;
   var j = 0;
   var p = 0;
   g = year % 19;
   c = IntDiv(year, 100);
   h = (c - IntDiv(c, 4) - IntDiv(8 * c + 13, 25) + 19 * g + 15) % 30;
   i = h - IntDiv(h, 28) * (1 - IntDiv(h, 28)
      * IntDiv(29, h + 1) * IntDiv(21 - g, 11));
   j = (year + IntDiv(year, 4) + i + 2 - c + IntDiv(c, 4)) % 7;
   p = i - j + 28;
   wDay = p;
   wMonth = 4;
   if (p > 31)
      wDay = p - 31;
   else
      wMonth = 3;
}
function EasterOrthodox (yr, jDay, jMonth)
/* Even though the Julian calendar is no longer in use
   Orthodox Easters are still based on this calendar
   NOTE! JULIAN Easter Date must be calculated first!
   This function converts Julian March and April
   Easter Sunday dates to Gregorian calendar dates  */
{
   var extra = 0;
   var tmp = 0;
   oDay = 0;
   oMonth = 0;
   if ((yr > 1582) && (yr <= 4099)) {
      extra = 10;
   if (yr > 1600) {
         tmp = IntDiv(yr, 100) - 16;
         extra = extra + tmp - IntDiv(tmp, 4);
      }
      oDay = jDay + extra;
      oMonth = jMonth;
      if ((oMonth == 3) && (oDay > 31)) {
         oMonth = 4;
         oDay = oDay - 31;
      }
      if ((oMonth == 4) && (oDay > 30)) {
         oMonth = 5;
         oDay = oDay - 30;
      }
   }
}
//-->
</script>


Matlab Easter Date Calculator()

function [m, d] = easter(y)
% EASTER Easter date calculation for years 1583 to 4099
%
% y is a 4 digit year 1583 to 4099
%
% Using [m, d] = easter(y)
% d returns the day of the month of Easter
% m returns the month of Easter
%
% Using s = easter(y)
% s returns the Matlab serial date number for Easter
%
% Easter Sunday is the Sunday following the Paschal Full Moon
% (PFM) date for the year
%
% This algorithm is an arithmetic interpretation of the 3 step
% Easter Dating Method developed by Ron Mallen 1985, as a vast
% improvement on the method described in the Common Prayer Book
%
% Because this algorithm is a direct translation of the
% official tables, it can be easily proved to be 100% correct
%
% This algorithm derives values by sequential inter-dependent
% calculations, so ... DO NOT MODIFY THE ORDER OF CALCULATIONS!
%
% All variables are integer data types
%
% It's free!  Please do not modify code or comments!
% ==========================================================
%   Dim FirstDig, Remain19, temp    % intermediate results
%   Dim tA, tB, tC, tD, tE          % table A to E results
   FirstDig = fix(y / 100);         % first 2 digits of year
   Remain19 = mod(y, 19);           % remainder of year / 19
   % calculate PFM date
   temp = fix((FirstDig - 15) / 2) + 202 - 11 * Remain19;
   if FirstDig > 26, temp = temp - 1; end;
   if FirstDig > 38, temp = temp - 1; end;
   % A really long line :) Use Matlab's ... 3dots to break it up.
   if ((FirstDig == 21) | (FirstDig == 24) | (FirstDig == 25) | ...
      (FirstDig == 33) | (FirstDig == 36) | (FirstDig == 37)),
        temp = temp - 1;
   end;
   temp = mod(temp, 30);
   tA = temp + 21;
   if temp == 29, tA = tA - 1; end;
   if (temp == 28) & (Remain19 > 10), tA = tA - 1; end;
   % find the next Sunday
   tB = mod((tA - 19), 7);
   tC = mod((40 - FirstDig), 4);
   if tC == 3, tC = tC + 1; end;
   if tC > 1,  tC = tC + 1; end;
   temp = mod(y, 100);
   tD = mod((temp + fix(temp / 4)), 7);
   tE = mod((20 - tB - tC - tD) , 7) + 1;
   d = tA + tE;
  % return the date
   if d > 31,
      d = d - 31;
      m = 4;
   else
      m = 3;
   end;
  % check output arguments
  if nargout == 0,
    m = datenum(y,m,d);
  elseif nargout == 1,
    m = datenum(y,m,d);
  end;
return;


Home > Popular Science > Calendar & Easter > Easter Algorithms Easter Date FAQ < back back       ^ top top       next next > A Perpetual Calendar