Bereken Pasen (Oracle PL/SQL)

Gisteren blogde ik over een (redelijk eenvoudige) javascript functie welke de datum van paaszondag in een gegeven jaar berekent. Vandaag heb ik deze functie in een PL/SQL package gezet en gebruikt om ook andere feestdagen, zoals goede vrijdag en hemelvaart te kunnen berekenen.

De functie zelf ziet er als volgt uit:

  function f_calc_easter ( a in number )
    return date
  is
    g number    := mod(a,19)+1;           /* golden number */
    c number    := floor(a/100)+1;        /* century */
    x number    := floor(3*c/4)-12;       /* correction for non leap years */
    y number    := floor(((8*c)+5)/25)-5; /* moon correction */
    z number    := floor(5*a/4)-10-x;     /* Sunday */
    m number(2) := 3;                     /* March */
  
    e number;                             /* epacta */
    n number;                             /* full moon */
    p number(2);                          /* Easter Sunday */ 
  begin
    /* calculate epacta */
    e := mod(((11*g)+20+y-x),30); 
  
    if ( (e = 24 or e = 25) and g > 11 )
    then
      e := e + 1;
    end if;
  
    /* calculate full moon */
    n := 44-e;
  
    if ( n < 21 )
    then
      n := n + 30;
    end if;
  
    /* calculate Easter Sunday */
    p := n+7-mod((z+n),7);
  
    if ( p > 31 ) 
    then
      p := p - 31;
      m := m + 1;
    end if;

    /* return Easter Sunday as a date */
    return to_date( a||'-'||m||'-'||p, 'yyyy-mm-dd' );
  end f_calc_easter;

Ik heb er in dit geval voor gekozen de namen van de parameter en variabelen gelijk te houden aan die in de javascript functie.

De package waar deze functie in staat heb ik pkg_calc_holidays genoemd. Omdat ik niet wil dat deze functie rechtstreeks wordt aangeroepen, heb ik deze niet in de package specification gezet. De verderop beschreven procedure p_print_holidays wil ik wel buiten de package kunnen aangeroepen.

create or replace package pkg_calc_holidays 
as
  procedure p_print_holidays ( p_year in number );
end;

In de package body heb ik procudere p_print aangemaakt om dbms_output.put_line aan te roepen.

  procedure p_print ( p_string varchar2 )
  is
  begin
    dbms_output.put_line ( p_string );
  end p_print;

Ik heb er in dit geval voor gekozen om de berekende data naar het scherm te schrijven. Procedure p_print_holidays ziet er dan als volgt uit.

  procedure p_print_holidays ( p_year in number )
  is
    g_easter date;
  begin
    /* calculate Easter Sunday */
    g_easter := f_calc_easter ( p_year );

    /* calculate and print holidays to screen */ 
    p_print ('Goede Vrijdag:   '||to_char(g_easter-2,'dd-mm-yyyy'));
    p_print ('Paaszondag:      '||to_char(g_easter,'dd-mm-yyyy'));
    p_print ('Paasmaandag:     '||to_char(g_easter+1,'dd-mm-yyyy'));
    p_print ('Hemelvaart:      '||to_char(g_easter+39,'dd-mm-yyyy'));
    p_print ('Pinksterzondag:  '||to_char(g_easter+49,'dd-mm-yyyy'));
    p_print ('Pinkstermaandag: '||to_char(g_easter+50,'dd-mm-yyyy'));
  end p_print_holidays;

De met f_calc_easter berekende datum en de daarvan afgeleide data zouden ook op andere wijze gebruikt kunnen worden. Bijvoorbeeld door ze naar een tabel weg te schrijven. Of als basis voor het bepalen van afwijkende openingstijden van bijvoorbeeld een winkel.

De procedure zou in een SQL editor nu als volgt aangeroepen kunnen worden:

begin
  pkg_calc_holidays.p_print_holidays ( 2018 ); 
end;

Met als resultaat:

Goede Vrijdag:   30-03-2018
Paaszondag:      01-04-2018
Paasmaandag:     02-04-2018
Hemelvaart:      10-05-2018
Pinksterzondag:  20-05-2018
Pinkstermaandag: 21-05-2018

Statement processed.

0.00 seconds

De volledige code staat op deze pagina.

Vragen over deze code en/of mogelijke toepassingen? Neem contact met mij op via dit contactformulier.

Geef een reactie

Vul je gegevens in of klik op een icoon om in te loggen.

WordPress.com logo

Je reageert onder je WordPress.com account. Log uit /  Bijwerken )

Google photo

Je reageert onder je Google account. Log uit /  Bijwerken )

Twitter-afbeelding

Je reageert onder je Twitter account. Log uit /  Bijwerken )

Facebook foto

Je reageert onder je Facebook account. Log uit /  Bijwerken )

Verbinden met %s