Ever wondered how they Easter date is determined? And, even more important, how it is to be maintained in you application. Manually updating the date every year is an option, but it’s always better to calculate it on the fly. It’s not easy because it depends on the age of the moon at january 1st and uses the moonyear cycle.
So, here’s some pl/sql which calculates Easter sunday for any given year:
create or replace function bepaal_paasdatum( p_jaar in number default to_numbeR(to_char( sysdate, ‘yyyy’) )) return date is
VolleMaan Date;
GuldenGetal pls_Integer;
SchrikkelDg pls_Integer := 14;
Epacta pls_Integer;
KritEpacta pls_Integer;
begin
/* first we calculate the “golden number” of the year; we divide the year with the years in a moonyear cycle (19), and add 1
(see http://en.wikipedia.org/wiki/Golden_numbers)
*/
Guldengetal := mod( p_jaar, 19 ) +1;
/*
epacta is the age of the moon at januari 1st
*/
Epacta := mod((GuldenGetal * 11 )- SchrikkelDg + 2, 30);
/*
calculate the full moons in a year
*/
VolleMaan := to_Date(’13-03-‘||to_char( p_jaar), ‘dd-mm-yyyy’ ) + 31 – Epacta;
If (mod( p_jaar , 4) = 0 and mod(p_jaar, 100) != 0 ) or mod(p_jaar, 400) = 0
Then
VolleMaan := VolleMaan – 1;
end if;
—
If VolleMaan < to_Date(’22-03-‘||to_char( p_jaar), ‘dd-mm-yyyy’ )
Then
If GuldenGetal > 11
Then
KritEpacta := 26;
Else
KritEpacta := 25;
End If;
If Epacta < KritEpacta
Then
VolleMaan := VolleMaan + 29;
Else
VolleMaan := VolleMaan + 30;
End If;
End If;
vollemaan := vollemaan +1 ;
while to_char(vollemaan, ‘d’) != 1 –zondag zoeken
loop
vollemaan := vollemaan + 1;
end loop;
—
return( VolleMaan );
end;
/
The results:
PATRICK> begin
2 for i in 1990 .. 2010
3 loop
4 dbms_output.put_line( ‘jaar ‘||i||’; ‘|| bepaal_paasdatum(i));
5 end loop;
6 end;
7 /
jaar 1990; 15-APR-90
jaar 1991; 31-MAR-91
jaar 1992; 19-APR-92
jaar 1993; 11-APR-93
jaar 1994; 03-APR-94
jaar 1995; 16-APR-95
jaar 1996; 07-APR-96
jaar 1997; 30-MAR-97
jaar 1998; 12-APR-98
jaar 1999; 04-APR-99
jaar 2000; 23-APR-00
jaar 2001; 15-APR-01
jaar 2002; 31-MAR-02
jaar 2003; 20-APR-03
jaar 2004; 11-APR-04
jaar 2005; 27-MAR-05
jaar 2006; 16-APR-06
jaar 2007; 08-APR-07
jaar 2008; 20-APR-08
jaar 2009; 12-APR-09
jaar 2010; 04-APR-10
PL/SQL procedure successfully completed.
PATRICK>
I’ve checked the dates against easter dates found on internet, and it seems right. Except…. the date for next year! Sources on internet mention March 23th, 2008, but my function returns April 20th.
I hate to say I have no clue where the problem is. So, if you plan to use my function you’ll either should find the bug or implement it after 2008! Some people suggested I have a real Easter Egg in my code….
Can you tell me what is “zondag zoeken” in your code ??
I don’t like wordpress. it changes my quotes “‘”, it changes my formating and it cuts my text when I use a < sign.
In the above comment you should add the following line
< 10
You use the internet to check your values, but you can also use it for querying your values:
[pre]
select 2000 + level
, cast( to_timestamp_tz( extractValue( HTTPURITYPE( ‘www.holidaywebservice.com/Holidays/GBSCT/Dates/GBSCTHolidayDates.asmx/GetEaster?year=’
|| to_char( 2000 + level )
).getXML()
, ‘/dateTime’
, ‘xmlns=”http://www.27seconds.com/Holidays/GBSCT/Dates/”‘
)
, ‘YYYY-MM-DD”T”HH24:MI:SS.FF7TZH:TZM’
) as date
)
from dual connect by level
This blog again proves that everything has been done before 🙂 thanks for your input!
There’s a Knowledge Base article on doing precisely this at http://www.dizwell.com/prod/node/368
The function described there correctly tells you that Good Friday in 2008 will be on 21st March.
I was intrigued by this bug, and read through some Java based examples. It seems that the have an additional if statement ( if(n > 31) ) which causes the result to be correct for 2008. http://www.java2s.com/Code/Java/Development-Class/EastercomputethedayonwhichEasterfalls.htm