Diogenes
28.05.2002, 12:03
Es gibt in der Römisch-Katholischen Kirche 2 Typen von Feiertagen:
Feste Feste : Die finden immer an einem bestimmten Termin statt, wie zum Beispiel der Christtag, der immer am 25. Dezember gefeiert wird. Das sollte einfach sein.
Weniger einfach sind zugegebenermaßen die beweglichen Feste. Die sind alle relativ zum Ostersonntag gesetzt, wobei jeder Feiertag seinen eigenen Abstand zum Ostersonntag hat. Der wiederum ist der erste Sonntag, der auf den ersten Vollmond im Frühling folgt. Das ist die Definition. Jetzt kann man einen Algorithmus daraus basteln, wenn man die länge des tropischen Jahres (Zeit, die die Sonne braucht, um den Frühlingspunkt 2 mal zu erreichen) und des synodischen Monats (Zeit von Neumond zu Neumond) kennt. Und einen exakten Termin (Tag, Stunde, Minut, Sekunde) für 1 Vollmond braucht man auch. Noch eine Anmerkung: Das Gregorianische Kalenderjahr ist um etwa 0.0003 Tage länger als das astronomische, tropische Jahr. Macht die Sache ein wenig komplizierter.
Ich hab vor längerer Zeit mal einen Kalender geschrieben. Hier den wichtigen Ausschnitt aus der relevanten Routine zur Feiertagsberechnung (incl. der regionalen Feiertage):
void __fastcall CalcFeiertage(int jahr)
{
int t, ostern, o_tag, o_monat, a, b, c, d, e;
o_tag = o_monat = 0;
a = jahr % 19; b = jahr % 4; c = jahr % 7;
d = (19 * a + 24) % 30; e = (2 * b + 4 * c + 6 * d + 5) % 7;
if(d == 29 && e == 6)
{
o_tag = 29; o_monat = 4;
}
else if(d == 28 && e == 6)
{
o_tag = 18; o_monat = 4;
}
else
{
if(d + e < 10)
{
o_tag = 22 + d + e;
o_monat = 3;
}
else
{
o_tag = d + e - 9;
o_monat = 4;
}
}
ostern = DayOfYear(o_tag, o_monat, jahr);
AddFT(1, 1, "Neujahr", ALL);
AddFT(6, 1, "Hl. Drei Könige", BW | BAY | SAA);
AddFT(14, 2, "Valentin", 0);
AddFT(ostern - 48, 0, "Rosenmontag", 0);
AddFT(ostern - 47, 0, "Fastnacht", 0);
AddFT(ostern - 46, 0, "Aschermittwoch", 0);
// 20.03. Frühlingsanfang
if(jahr == 1980) AddFT(6, 4, "Beginn Sommerzeit", 0);
else if(jahr > 1980) AddFT(DayOfYear(31, 3, jahr) - WotaSo(31, 3, jahr), 0, "Beginn Sommerzeit", 0);
AddFT(ostern - 7, 0, "Palmsonntag", 0);
AddFT(ostern - 3, 0, "Gründonnerstag", 0);
AddFT(ostern - 2, 0, "Karfreitag", ALL);
AddFT(ostern, 0, "Ostern", ALL);
AddFT(ostern + 1, 0, "Ostern", ALL);
AddFT(ostern + 7, 0, "Weißer Sonntag", 0);
AddFT(1, 5, "Maifeiertag", ALL);
t = DayOfYear(30, 4, jahr) - WotaSo(30, 4, jahr) + 14;
if(t == ostern + 49) t -= 7;
AddFT(t, 0, "Muttertag", ALL);
AddFT(ostern + 39, 0, "Christi Himmelfahrt", ALL);
AddFT(ostern + 49, 0, "Pfingsten", ALL);
AddFT(ostern + 50, 0, "Pfingsten", ALL);
// 21.06. Sommeranfang
AddFT(ostern + 60, 0, "Fronleichnam", BW | BAY | HES | NRW | RPL | SAR);
AddFT(27, 6, "Siebenschläfer", 0);
AddFT(15, 8, "Mariä Himmelfahrt", SAR | BAY);
// 22.09. Herbstanfang
AddFT(29, 9, "Michaelis", 0);
AddFT(DayOfYear(29, 9, jahr) + 7 - WotaSo(29, 9, jahr), 0, "Erntedank", 0);
AddFT(3, 10, "Deutsche Einheit", ALL);
if(jahr == 1980) AddFT(28, 9, "Ende Sommerzeit", 0);
else if(jahr > 1980 && jahr <= 1995) AddFT(DayOfYear(30, 9, jahr) - WotaSo(30, 9, jahr), 0, "Ende Sommerzeit", 0);
else if(jahr >= 1996) AddFT(DayOfYear(31, 10, jahr) - WotaSo(31, 10, jahr), 0, "Ende Sommerzeit", 0);
AddFT(31, 10, "Reformationstag", BRB | MVP | SAX | SAA | THR);
AddFT(1, 11, "Allerheiligen", BW | BAY | NRW | RPL | SAR);
AddFT(11, 11, "Martin", 0);
AddFT(DayOfYear(24, 12, jahr) - WotaSo(24, 12, jahr) - 5 * 7, 0, "Volkstrauertag", 0);
AddFT(DayOfYear(24, 12, jahr) - WotaSo(24, 12, jahr) - 4 * 7 - 4, 0, "Buß- und Bettag", SAX);
AddFT(DayOfYear(24, 12, jahr) - WotaSo(24, 12, jahr) - 4 * 7, 0, "Totensonntag", 0);
t = DayOfYear(24, 12, jahr) - WotaSo(24, 12, jahr);
AddFT(t, 0, "4. Advent", 0);
AddFT(t - 7, 0, "3. Advent", 0);
AddFT(t - 14, 0, "2. Advent", 0);
AddFT(t - 21, 0, "1. Advent", 0);
AddFT(6, 12, "Nikolaus", 0);
// 21.12. Winteranfang
AddFT(24, 12, "Heiligabend", 0);
AddFT(25, 12, "Weihnachten", ALL);
AddFT(26, 12, "Weihnachten", ALL);
AddFT(31, 12, "Silvester", 0);
}
int __fastcall DayOfYear(int t, int m, int j)
{
TDateTime present, StartOfYear;
unsigned short day, month, year;
present = TDateTime(j, m, t);
present.DecodeDate(&year, &month, &day);
StartOfYear = EncodeDate(year, 1, 1);
return (int) present - (int) StartOfYear + 1;
}
int __fastcall WotaSo(int t, int m, int j)
{
TDateTime dt;
dt = EncodeDate(j, m, t);
return dt.DayOfWeek() - 1;
}
Die letzten beiden Routinen sind C++Builder-spezifisch, können aber natürlich in andere Programmsprachen sinngemäß übersetzt werden.
AddFT kriegt übrigens vier Parameter: Tag, Monat, Bezeichnung, Bundesländer. Bundesländer ist ein Bitfeld. Wenn Monat = 0, gibt Tag den Tag im ganzen Jahr an.
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.