Wiki Home

Algorithm Easter Date


Namespace: Wiki
05/09/2003 - Steven Blake I had to determine holidays for a NYSE routine. Empty results were valid only when the stock market was closed. Of the nine weekdays when the NYSE takes a holiday, Good Friday was a moving target. It's occurrence depends upon the Paschal Full Moon which shines some night between March 21 through April 18.
I found a web site that provided several algorithms that employ just integer math. I have coded two in the example below. The Oudin algorithm is valid for all years in the Gregorian calendar, 1583 and onwards. The Carter algorithm is simpler but only works in two centuries, 1900 through 2099.
The web site source for these Easter algorithms (and extensive discussion of holidays in general) is http://smart.net/~mmontes/ec-cal.html designed by Marcos J. Montes.
**************************************************************************
* Function: GET_EASTER()
*  Purpose: Determine Gregorian Easter Sunday date for year 1583 upward
*           (Western churches only)
* Argument: nTheYear - Integer value of the year you wish to find Easter day
*           lLongVer - Logical to force Oudin version rather than Carter
*  Returns: d_Easter - Date value of Easter
**************************************************************************
LPARAMETER nTheYear, lLongVer
LOCAL nStep001, nStep002, nStep003, dSeedVal, d_Easter, nYear004, nYear019, ;
      nCentury, nCent004, nCent025, nCent030, nCent028, nE_Month, nE_DtOfM

*-- Initialize the return value
d_Easter = {}

DO CASE
CASE .NOT. lLongVer .AND. BETWEEN(nTheYear, 1900, 2099)
   ***********************************************
   *  Algorithm finds the date of Easter from 1900 to 2099 (by Carter)
   *     Calculate B = 225 - 11(Y MOD 19).
   *     Calculate D = ((B-21) MOD 30) + 21.
   *     If D is greater than 48 subtract 1 from it.
   *     Calculate E = (Y + [Y/4] + D + 1) MOD 7 .
   *     Calculate Q= D + 7 - E.
   *
   *  If Q is < 32 then Q is Easter day in March.
   *  If Q is > 31 then Q - 31 is Easter day in April.
   ***********************************************

   nStep001 = 225 - INT(11 * (nTheYear % 19))
   nStep002 = INT((nStep001 -21) % 30) + 21
   nStep002 = nStep002 - IIF(nStep002 > 48, 1, 0)
   nStep003 = INT(nTheYear + INT(nTheYear/4) + nStep002 + 1) % 7

   dSeedVal = CTOD("^" + STR(nTheYear, 4) + "/03/01") -1
   d_Easter = dSeedVal + (nStep002 + 7 - nStep003)

CASE nTheYear > 1582
   **************************************************************************
   *  A more complex algorithm by Oudin (1940)
   *     century = year/100
   *     G = year % 19
   *     K = (century - 17)/25
   *     I = (century - century/4 - (century - K)/3 + 19*G + 15) % 30
   *     I = I - (I/28)*(1 - (I/28)*(29/(I + 1))*((21 - G)/11))
   *     J = (year + year/4 + I + 2 - century + century/4) % 7
   *     L = I - J
   *
   *  EasterMonth = 3 + (L + 40)/44
   *  EasterDay = L + 28 - 31*(EasterMonth/4)
   *
   **************************************************************************

   nYear004 = INT(nTheYear / 4)
   nYear019 = INT(nTheYear % 19)

   nCentury = INT(nTheYear / 100)
   nCent004 = INT(nCentury / 4)
   nCent025 = INT((nCentury - 17) / 25)
   nCent030 = INT((nCentury - nCent004 - INT((nCentury - nCent025) / 3) + (19 * nYear019) + 15) % 30)
   nCent028 = INT(nCent030 / 28)

   nStep001 = nCent030 - nCent028 * (1 - nCent028 * INT(29 / (nCent030 + 1)) * INT((21 - nYear019) / 11))
   nStep002 = nStep001 - INT((nTheYear + nYear004 + nStep001 + 2 - nCentury + nCent004) % 7)

   nE_Month = 3 + INT((nStep002 + 40) / 44)
   nE_DtOfM = nStep002 + 28 - (31 * INT(nE_Month /4))

   d_Easter = CTOD("^" + STR(nTheYear, 4) + "/0" + STR(nE_Month, 1) + "/" + PADL(nE_DtOfM, 2, "0"))

ENDCASE

RETURN d_Easter

Category Code Samples Category UDF Category UDFDates
( Topic last updated: 2005.02.09 11:53:50 AM )