views:

344

answers:

4

So, here's a funny little programming challenge. I was writing a quick method to determine all the market holidays for a particular year, and then I started reading about Easter and discovered just how crazy* the logic is for determining its date--the first Sunday after the Paschal Full Moon following the spring equinox! Does anybody know of an existing function to calculate the date of Easter for a given year?

Granted, it's probably not all that hard to do; I just figured I'd ask in case somebody's already done this. (And that seems very likely.)

UPDATE: Actually, I'm really looking for the date of Good Friday (the Friday before Easter)... I just figured Easter would get me there. And since I'm in the U.S., I assume I'm looking for the Catholic Easter? But perhaps someone can correct me on that if I'm wrong.

*By "crazy" I meant, like, involved. Not anything offensive...

+9  A: 

Python: using dateutil's easter() function.

>>> from dateutil.easter import *
>>> print easter(2010)
2010-04-04
>>> print easter(2011)
2011-04-24

The functions gets, as an argument, the type of calculation you like:

EASTER_JULIAN   = 1
EASTER_ORTHODOX = 2
EASTER_WESTERN  = 3

You can pick the one relevant to the US.

Reducing two days from the result would give you Good Friday:

>>> from datetime import timedelta
>>> d = timedelta(days=-2)
>>> easter(2011)
datetime.date(2011, 4, 24)
>>> easter(2011)+d
datetime.date(2011, 4, 22)

Oddly enough, someone was iterating this, and published the results in Wikipedia's article about the algorithm:

alt text

Adam Matan
+4  A: 

If you're looking for algorithms and examples try http://www.merlyn.demon.co.uk/estrdate.htm. There's a Javascript example on the site that could be ported to other languages plus some rather detailed algorithms and explanations. It will take some reading though!

Andy E
+1 Very comprehensive link.
Adam Matan
+5  A: 

in SQL Server Easter Sunday would look like this, scroll down for Good Friday

CREATE FUNCTION dbo.GetEasterSunday 
( @Y INT ) 
RETURNS SMALLDATETIME 
AS 
BEGIN 
    DECLARE     @EpactCalc INT,  
        @PaschalDaysCalc INT, 
        @NumOfDaysToSunday INT, 
        @EasterMonth INT, 
        @EasterDay INT 

    SET @EpactCalc = (24 + 19 * (@Y % 19)) % 30 
    SET @PaschalDaysCalc = @EpactCalc - (@EpactCalc / 28) 
    SET @NumOfDaysToSunday = @PaschalDaysCalc - ( 
        (@Y + @Y / 4 + @PaschalDaysCalc - 13) % 7 
    ) 

    SET @EasterMonth = 3 + (@NumOfDaysToSunday + 40) / 44 

    SET @EasterDay = @NumOfDaysToSunday + 28 - ( 
        31 * (@EasterMonth / 4) 
    ) 

    RETURN 
    ( 
        SELECT CONVERT 
        (  SMALLDATETIME, 
                 RTRIM(@Y)  
            + RIGHT('0'+RTRIM(@EasterMonth), 2)  
            + RIGHT('0'+RTRIM(@EasterDay), 2)  
    ) 
END 
GO

Good Friday is like this and it uses the Easter function above

CREATE FUNCTION dbo.GetGoodFriday 
( 
    @Y INT 
) 
RETURNS SMALLDATETIME 
AS 
BEGIN 
    RETURN (SELECT dbo.GetEasterSunday(@Y) - 2) 
END 
GO

From here: http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html

SQLMenace
I *think* you were the first to actually post code that does this. Kudos, my friend... and thanks.
Dan Tao
+2  A: 

When it came for me to write this (traffic prediction based on day of week and holiday), I gave up on trying to write it by myself. I found it somewhere on the net. The code was public domain, but...

sigh

see for yourself.

void dateOfEaster(struct tm* p)
{
    int Y = p->tm_year;
    int a = Y % 19;
    int b = Y / 100;
    int c = Y % 100;
    int d = b / 4;
    int e = b % 4;
    int f = (b + 8) / 25;
    int g = (b - f + 1) / 3;
    int h = (19 * a + b - d - g + 15) % 30;
    int i = c / 4;
    int k = c % 4;
    int L = (32 + 2 * e + 2 * i - h - k) % 7;
    int m = (a + 11 * h + 22 * L) / 451;
    p->tm_mon = ((h + L - 7 * m + 114) / 31 ) - 1;
    p->tm_mday = ((h + L - 7 * m + 114) % 31) + 1;
    p->tm_hour = 12;
    const time_t tmp = mktime(p);
    *p = *localtime(&tmp);  //recover yday from mon+mday
}

Some questions are better left unasked.

I feel lucky that all moving holidays in my country are a fixed offset from the date of Easter.

SF.
+1 Nice. Try figuring out DST in my country, it has some nice anecdotes. http://en.wikipedia.org/wiki/Israel_Summer_Time
Adam Matan
It looks like the developer who wrote this gave j the shaft.
Dan Tao
I think this is actually Donald Knuth's algorithm: http://www.linuxtopia.org/online_books/programming_books/python_programming/python_ch38.html
Richard Nienaber