Da viele Feiertage (z.B. Rosenmontag) eine Abhängigkeit zum Osterdatum besitzen, benötigt man zunächst eine Funktion zur Berechnung des Osterdatums; genauer gesagt zur Bestimmung von Ostersonntag:
create or replace function easter_day ( p_year_in in integer ) return date as v_k integer; v_m integer; v_s integer; v_a integer; v_d integer; v_r integer; v_og integer; v_sz integer; v_oe integer; v_os integer; v_day integer; v_month integer; begin v_k := floor(p_year_in / 100); v_m := 15 + floor((3 * v_k + 3) / 4) - floor((8 * v_k + 13) / 25); v_s := 2 - floor((3 * v_k + 3) / 4); v_a := mod(p_year_in, 19); v_d := mod((19 * v_a + v_m), 30); v_r := floor(v_d / 29) + (floor(v_d / 28) - floor(v_d / 29)) * floor(v_a / 11); v_og := 21 + v_d - v_r; v_sz := 7 - mod((p_year_in + floor(p_year_in / 4) + v_s), 7); v_oe := 7 - mod(v_og - v_sz, 7); v_os := v_og + v_oe; if (v_os <= 31) then v_day := v_os; v_month := 3; else v_day := v_os - 31; v_month := 4; end if; return to_date(v_day || '.' || v_month || '.' || p_year_in, 'DD.MM.YYYY'); end easter_day;Dabei handelt es sich im Wesentlichen um die ergänzte Osterformel von Carl-Friedrich Gauß; diese wurde durch Hermann Kinkelin und Christian Zeller dahingehend ergänzt, dass Ausnahmeregeln in der Formel berücksichtigt werden. Siehe dazu auch den entsprechenden Eintrag auf der deutschsprachigen Seite von Wikipedia.
Kommen wir nun zur eigentlichen Table-Function, für die zuächst die Objekt-Typen erstellt werden müssen:
create type holiday_t as object ( holiday_date date, holiday_name varchar2(30), holiday_desc varchar2(100) ); / create type holiday_tab as table of holiday_t; /Die eigentliche Table-Function liefert nun die "Feiertage" der jeweiligen Jahre:
create or replace function german_holidays ( p_year_start_in in integer, p_year_end_in in integer ) return holiday_tab pipelined as v_easter_day date; begin for y in p_year_start_in .. p_year_end_in loop v_easter_day := easter_day(y); pipe row ( holiday_t( to_date('01.01.' || y, 'DD.MM.YYYY'), 'Neujahrstag', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( to_date('06.01.' || y, 'DD.MM.YYYY'), 'Heilige Drei Könige', 'Nur BW, BY und ST')); pipe row ( holiday_t( v_easter_day - interval '52' day, 'Weiberdonnerstag', '-')); pipe row ( holiday_t( v_easter_day - interval '48' day, 'Rosenmontag', '-')); pipe row ( holiday_t( v_easter_day - interval '46' day, 'Aschermittwoch', '-')); pipe row ( holiday_t( v_easter_day - interval '3' day, 'Gründonnerstag', '-')); pipe row ( holiday_t( v_easter_day - interval '2' day, 'Karfreitag', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( v_easter_day + interval '1' day, 'Ostermontag', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( to_date('01.05.' || y, 'DD.MM.YYYY'), 'Tag der Arbeit', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( v_easter_day + interval '39' day, 'Christi Himmelfahrt', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( v_easter_day + interval '50' day, 'Pfingstmontag', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( v_easter_day + interval '60' day, 'Fronleichnam', 'Nur BW, BY, HE, NW, RP')); pipe row ( holiday_t( to_date('08.08.' || y, 'DD.MM.YYYY'), 'Augsburger Friedensfest', 'Nur im Stadtgebiet Augsburg')); pipe row ( holiday_t( to_date('08.08.' || y, 'DD.MM.YYYY'), 'Mariä Himmelfahrt', 'Nur SL und Teilen von BY')); pipe row ( holiday_t( to_date('03.10.' || y, 'DD.MM.YYYY'), 'Tag der Deutschen Einheit', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( to_date('31.10.' || y, 'DD.MM.YYYY'), 'Reformationstag', 'Nur BB, MV, SL, SN und TH')); pipe row ( holiday_t( to_date('01.11.' || y, 'DD.MM.YYYY'), 'Allerheiligen', 'Nur BW, BY, NW, RP und SL')); pipe row ( holiday_t( to_date('11.11.' || y, 'DD.MM.YYYY'), 'Karnevalsbeginn', '-')); pipe row ( holiday_t( to_date('25.12.' || y, 'DD.MM.YYYY'), '1. Weihnachtstag', 'Gesetzlicher Feiertag')); pipe row ( holiday_t( to_date('26.12.' || y, 'DD.MM.YYYY'), '2. Weihnachtstag', 'Gesetzlicher Feiertag')); end loop; end german_holidays;Für das Jahr 2012 erhält man dann:
select * from table(german_holidays(2012, 2012));
HOLIDAY_DATE HOLIDAY_NAME HOLIDAY_DESC ------------- ------------------------------ ---------------------------- 01.01.12 Neujahrstag Gesetzlicher Feiertag 06.01.12 Heilige Drei Könige Nur BW, BY und ST 16.02.12 Weiberdonnerstag - 20.02.12 Rosenmontag - 22.02.12 Aschermittwoch - 05.04.12 Gründonnerstag - 06.04.12 Karfreitag Gesetzlicher Feiertag 09.04.12 Ostermontag Gesetzlicher Feiertag 01.05.12 Tag der Arbeit Gesetzlicher Feiertag 17.05.12 Christi Himmelfahrt Gesetzlicher Feiertag 28.05.12 Pfingstmontag Gesetzlicher Feiertag 07.06.12 Fronleichnam Nur BW, BY, HE, NW, RP 08.08.12 Augsburger Friedensfest Nur im Stadtgebiet Augsburg 08.08.12 Mariä Himmelfahrt Nur SL und Teilen von BY 03.10.12 Tag der Deutschen Einheit Gesetzlicher Feiertag 31.10.12 Reformationstag Nur BB, MV, SL, SN und TH 01.11.12 Allerheiligen Nur BW, BY, NW, RP und SL 11.11.12 Karnevalsbeginn - 25.12.12 1. Weihnachtstag Gesetzlicher Feiertag 26.12.12 2. Weihnachtstag Gesetzlicher FeiertagMit Bezug auf das vorherige Posting ergibt sich nun die Möglichkeit, die Zeitdimension um die Feiertage zu erweitern.
Ich vermisse den Buß- und Bettag....erfordert dieser eine gesonderte Berechnung?
AntwortenLöschenVorletzter Mittwoch vor 1. Advent bzw. o'Ton Wikipedia: elf Tage vor dem ersten Adventssonntag.
LöschenAlso ja, rechnen.
Danke Thomas, super Code-Snippets.
AntwortenLöschenEin Tippfehler: Mariä Himmelfahrt ist am 15.08.