Algorithmensammlung: Kalender: Feiertage

Aus Wikibooks

Algorithmensammlung: Kalender

Ostersonntag[Bearbeiten]

Das Osterfest ist ein bewegliches Fest, d.h. das Datum liegt in jedem Jahr anders. Hier werden die Grundlagen der Berechnungen behandelt:

C#[Bearbeiten]

Die Methode benennt die Variablen analog zur ergänzten Osterformel von Gauß.

/// <summary>
/// Errechnet das Datum des Ostersonntags aus dem übergebenen Jahr
/// </summary>
/// <param name="int">Das Jahr in YYYY Schreibweise</param>
/// <returns>Das errechnete Datum des Ostersonntags in dem angegebene Jahr</returns>
private DateTime GetOstersonntag(int jahr) {
  int x = jahr;		// das Jahr
  int k;			// die Säkularzahl
  int m;			// die säkulare Mondschaltung
  int s;			// die säkulare Sonnenschaltung
  int a;			// der Mondparameter
  int d;			// der Keim für den ersten Vollmond im Frühling
  int r;			// die kalendarische Korrekturgröße
  int og;			// die Ostergrenze
  int sz;			// der ersten Sonntag im März
  int oe;			// die Entfernung des Ostersonntags von der Ostergrenze
  int os;			// das Datum des Ostersonntags als Märzdatum (32.März = 1.April)
  int OsterTag;
  int OsterMonat;
  
  k = x / 100;
  m = 15 + (3 * k + 3) / 4 - (8 * k + 13) / 25;
  s = 2 - (3 * k + 3) / 4;
  a = x % 19;
  d = (19 * a + m) % 30;
  r = (d + a / 11) / 29;
  og = 21 + d - r;
  sz = 7 - (x + x / 4 + s) % 7;
  oe = 7 - (og - sz) % 7;
  os = og + oe;
  
  OsterMonat = 2 + (int)(os + 30) / 31;
  OsterTag = os - 31 * ((int)OsterMonat / 4);

  return new DateTime(jahr, OsterMonat, OsterTag);
}

Lotus Script[Bearbeiten]

Der Algorithmus wird im Wesentlichen von Visual Basic For Applications übernommen. Schritt 11 Ostersonntag bestimmen muss abgewandelt werden, weil Lotus Script nicht mit überlaufenden Tagesangaben rechnen kann.

    ' 11. Ostersonntag bestimmen
    Dim OM as Long       
    OM = 3     
    If (OS > 31) Then    
        OS = OS - 31        
        OM = 4        
    End If
    OsterSonntag = DateSerial(Jahr, OM, OS)

Visual Basic For Applications[Bearbeiten]

Der hier vorgestellte Algorithmus ist der in der Wikipedia unter „Gaußsche Osterformel“ wiedergegebene Algorithmus von Lichtenberg.

Die Kommentare wurden aus der Wikipedia übernommen.

Die Funktion erwartet das Argument Jahr als Ganzzahl im vollen Format (also beispielsweise 2012, nicht 12) und gibt das Datum des Ostersonntags als Wert vom Datentyp Datum zurück. Der Datentyp Date beginnt mit seiner Zählung ab 1904. Wegen des Aufbaus ist es möglich, dass Programme mit Date vor 1904, die in diesem Datentyp übergeben werden, nicht korrekt arbeiten können.

Public Function OsterSonntag(Jahr As Long) As Date
    Dim A As Long, K As Long, M As Long, D As Long, S As Long
    Dim R As Long, OG As Long, SZ As Long, OE As Long, OS As Long
    
    ' 1. die Säkularzahl
    K = Jahr \ 100
    ' 2. die säkulare Mondschaltung
    M = 15 + (3 * K + 3) \ 4 - (8 * K + 13) \ 25
    ' 3. die säkulare Sonnenschaltung
    S = 2 - (3 * K + 3) \ 4
    ' 4. den Mondparameter
    A = Jahr Mod 19
    ' 5. den Keim für den ersten Vollmond im Frühling
    D = (19 * A + M) Mod 30
    ' 6. die kalendarische Korrekturgröße
    R = (D + A \ 11) \ 29
    ' 7. die Ostergrenze
    OG = 21 + D - R
    ' 8. den ersten Sonntag im März
    SZ = 7 - (Jahr + Jahr \ 4 + S) Mod 7
    ' 9. die Entfernung des Ostersonntags von der Ostergrenze (Osterentfernung in Tagen)
    OE = 7 - (OG - SZ) Mod 7
    '10. das Datum des Ostersonntags als Märzdatum (32. März = 1. April usw.)
    OS = OG + OE  
    '11. Ostersonntag bestimmen
    OsterSonntag = DateSerial(Jahr, 3, OS)

End Function

Buß- und Bettag[Bearbeiten]

C#[Bearbeiten]

Autor: Sheitman[1]
Methode als Teil von Feiertage.cs

/// <summary>
/// Errechnet das Datum des Buß- und Bettags aus dem übergebenen Jahr
/// </summary>
/// <param name="year">Das Jahr YYYY als integer-Wert</param>
/// <returns>Das errechnete Datum des Buß- und Bettags in dem angegebenen Jahr</returns>
internal DateTime GetBussUndBettag(int year)
{
	//	Der Buß- und Bettag ist immer ein Mittwoch, er liegt zwischen dem 16. und 22. November
	return GetLastWeekday(new DateTime(year, 11, 22), DayOfWeek.Wednesday);
}
		
/// <summary>
/// Bestimmt innerhalb der letzten 7 Tage das Datum mit dem gewünschten Wochentag.  
/// </summary>
/// <param name="startDate">Ausgangsdatum, und zwar das letztmögliche Datum innerhalb 
/// des Bereichs von 7 Tagen (Beispiel: in einem Bereich Do/Fr/Sa/So/Mo/Di/Mi der Mittwoch)</param>
/// <param name="targetDayOfWeek">Der gewünschte Wochentag (im Beispiel der Mittwoch)</param>
/// <returns>Das Datum mit dem gewünschten Wochentag innerhalb der letzten 7 Tage.</returns>
public static DateTime GetLastWeekday(DateTime startDate, DayOfWeek targetDayOfWeek) 
{
	DayOfWeek startDayOfWeek = startDate.DayOfWeek;
	if (startDayOfWeek == targetDayOfWeek) {
          return startDate;
	}
	int diff = 0;
	if (startDayOfWeek < targetDayOfWeek) {
          diff = targetDayOfWeek - startDayOfWeek - 7;
	} else if (startDayOfWeek > targetDayOfWeek) {
          diff = targetDayOfWeek - startDayOfWeek;
	}
	return startDate.AddDays(diff);
}

Visual Basic For Applications[Bearbeiten]

Die Funktion berechnet den  Buß- und Bettag. Sie erwartet das Argument Jahr als Ganzzahl im vollen Format (also beispielsweise 2012, nicht 12) und gibt das Datum des Buß- und Bettages als Datentyp Date zurück.

Der Datentyp Date beginnt mit seiner Zählung ab 1904. Wegen des Aufbaus ist es möglich, dass Programme mit Date vor 1904, die in diesem Datentyp übergeben werden, nicht korrekt arbeiten können.

Public Function BussBettag(Jahr As Long) As Date
    ' Vom 23.11. des Jahres zum ersten Mittwoch davor zurückrechnen
    BussBettag = DateSerial(Jahr, 11, 23) - Weekday(DateSerial(Jahr, 11, 23), vbThursday)
End Function

Python[Bearbeiten]

Die Tatsache, dass der Buß- und Bettag der erste Mittwoch vor (inklusive) dem 22. November, lässt sich verwenden um ein einfaches Pythonskript zur dessen Berechnung zu schreiben. Die Rückgabe ist ein Datum als Objekt der Date Klasse.

from datetime import date, timedelta

def calc_buss_und_bet_tag(year):
    last_possible_day = date(year,11,22)
    # calculate first wednesday before or on the day year-11-22
    buss_und_bet_tag = last_possible_day - timedelta((last_possible_day.weekday() - 2) % 7)
    return buss_und_bet_tag

Quellen[Bearbeiten]

  1. mycsharp.de (Forumsbeitrag) sowie die Klassenbibliothek von Jürgen (als zip-Datei zum Download)