PHP Kalender Teil 1, Feiertage berechnen

Fangen wir mit den normalen deutschen Feiertagen an, da sie relativ einfachen Regeln unterliegen. Man unterscheidet zwischen beweglichen und festen Feiertagen. Die beweglichen Feiertage richten sich dabei überwiegend nach dem Ostersonntag. Einige der nicht gesetzlichen Feiertage richten sich aber auch nach einem der Advents-Sonntage.

 
Ostersonntag berechnen

Die Berechnung des Ostersonntags ist wie folgt definiert: Der erste Sonntag nach dem ersten Vollmond im Frühling. Da sich das nicht ganz so einfach berechnen lässt, ist schon beim Lesen der Definition zu erahnen. Aber glücklicherweise gibt einem PHP geeignete Hilfsmittel an die Hand:

$ostern = easter_date($YY);

Wenn man es selbst berechnen möchte, findet man im Netz auch die passenden Formeln. Anbei eine Formel für Excel, die man sehr häufig bei Google findet:

=DATUM(B1;3;1)+REST((255-11*REST(B1;19)-21);30)+21+(REST((255-11*REST(B1;19)-21);30)+21>48)+6-REST(B1+GANZZAHL(B1/4)+REST((255-11*REST(B1;19)-21);30)+21+(REST((255-11*REST(B1;19)-21);30)+21>48)+1;7)

 
Die Adventszeit

Die Advents-Sonntage lassen sich generell leichter berechnen, dafür gibt es hier auch keine vorgefertigte PHP-Funktion. Erstmal brauchen wir nur ein Datum, vorzugsweise vom 1. Advent (erster Sonntag nach dem 26. November) oder vom 4. Advent (letzter Sonntag vor dem 25. Dezember). Ich habe mich für den 4. Advent entschieden.

$advent4 = strtotime("last Sunday",mktime(0,0,0,12,25,$YY));

Wem der Code-Schnipsel zu unverständlich ist, der setzte sich entweder mit dem PHP-Handbuch auseinander oder schaue sich den folgenden Code an, der das gleiche Ergebnis produziert:

$i=0;
$advent4 = mktime(0,0,0,12,25,$YY);
do {
  $advent4 -= 1*24*60*60;
  if(date("w",$advent4) == 0)
    $i++;
}while($i==0);

Sieht aber auch nicht viel besser aus ^^

 
Die Berechnung der Feiertage

Nachdem nun die beiden wichtigsten Zeitpunkte feststehen, macht man sich an die Berechnung der Feiertage. Da es in Deutschland leider von Bundesland zu Bundesland unterschiedliche gesetzliche Feiertage gibt, muss sich jeder die Liste ggf. auf seine eigenen Bedürfnisse zurechtstutzen. Wie die Autoren des zugehörigen Wikipedia-Artikels verzichte auch ich auf jene Feiertage, die ohnehin immer auf einen Sonntag fallen.

$YY = 2012;
$tag = 24*60*60;
$ostern = easter_date($YY);
$advent4 = strtotime("last Sunday",mktime(0,0,0,12,25,$YY));

$feiertag["neujahr"]                   = mktime(0,0,0,1,1,$YY);
$feiertag["heilige_drei_koenige"]      = mktime(0,0,0,1,6,$YY);
$feiertag["gruendonnerstag"]           = $ostern - (3*$tag);
$feiertag["karfreitag"]                = $ostern - (2*$tag);
$feiertag["ostermontag"]               = $ostern + (1*$tag);
$feiertag["tag_der_arbeit"]            = mktime(0,0,0,5,1,$YY);
$feiertag["christi_himmelfahrt"]       = $ostern + (39*$tag);
$feiertag["pfingstmontag"]             = $ostern + (50*$tag);
$feiertag["fronleichnam"]              = $ostern + (60*$tag);
$feiertag["maria_himmelfahrt"]         = mktime(0,0,0,8,15,$YY);
$feiertag["tag_der_deutschen_einheit"] = mktime(0,0,0,10,3,$YY);
$feiertag["reformationstag"]           = mktime(0,0,0,10,31,$YY);
$feiertag["allerheiligen"]             = mktime(0,0,0,11,1,$YY);
$feiertag["buss_und_bettag"]           = $advent4 - (32*$tag);
$feiertag["weihnachtstag1"]            = mktime(0,0,0,12,25,$YY);
$feiertag["weihnachtstag2"]            = mktime(0,0,0,12,26,$YY);

Einige Feiertage haben mehrere Definitionen, anhand derer man ihr Datum berechnen kann. Der Buß- und Bettag liegt wie im Code dargestellt 32 Tage vor dem 4. Advent. Er liegt aber ebenfalls am Mittwoch vor dem 23. November. Da ich erst spät über die Funktion strtotime() gelesen habe, habe ich mich in den meisten Fällen für die Nutzung des 4. Advent als Bezugspunkt bei der Berechnung entschieden. Außerdem finde ich es mit den Variablen angenehmer zu lesen, aber das muss jeder für sich selbst entscheiden. Hier zum Vergleich:

$YY=2012;

$feiertag["neujahr"]                   = mktime(0,0,0,1,1,$YY);
$feiertag["heilige_drei_koenige"]      = mktime(0,0,0,1,6,$YY);
$feiertag["gruendonnerstag"]           = strtotime("-3 days",easter_date($YY));
$feiertag["karfreitag"]                = strtotime("-2 days",easter_date($YY));
$feiertag["ostermontag"]               = strtotime("+1 day",easter_date($YY));
$feiertag["tag_der_arbeit"]            = mktime(0,0,0,5,1,$YY);
$feiertag["christi_himmelfahrt"]       = strtotime("+39 day",easter_date($YY));
$feiertag["pfingstmontag"]             = strtotime("+50 day",easter_date($YY));
$feiertag["fronleichnam"]              = strtotime("+60 day",easter_date($YY));
$feiertag["maria_himmelfahrt"]         = mktime(0,0,0,8,15,$YY);
$feiertag["tag_der_deutschen_einheit"] = mktime(0,0,0,10,3,$YY);
$feiertag["reformationstag"]           = mktime(0,0,0,10,31,$YY);
$feiertag["allerheiligen"]             = mktime(0,0,0,11,1,$YY);
$feiertag["buss_und_bettag"]           = strtotime("last Wednesday",mktime(0,0,0,11,23,$YY));
$feiertag["weihnachtstag1"]            = mktime(0,0,0,12,25,$YY);
$feiertag["weihnachtstag2"]            = mktime(0,0,0,12,26,$YY);

Nun kann man sich bei Bedarf weitere Feiertage oder sonstige Termine hinzufügen.

Mein Plan sieht eine Liste vor, die einem die Ereignisse des aktuellen Tages anzeigt sowie eine 7 Tage Vorschau. Enthalten sein sollen Geburtstage, Feiertage, Fun-Tage und ggf. auch Termine wie Konzerte und Festivals. Das ganze wird dann allerdings etwas komplexer werden als hier vorgestellt, schließlich brauch ich zur Unterscheidung noch Kategorien.

  1. 24. Oktober 2016, 21:27 | #1

    Moin ich freue mich über den alten Beitrag :).
    auch wenn es X Kalender Funktionen gibt (so sagte mir 2005 ein freund kopfschüttelnd, als ich meinen eigenen php Kalender strickte)… alleine zu Verständnis finde ich solche Beiträge super hilfreich.
    Danke!!!

  1. Bisher keine Trackbacks