C++ Builder Snippets  

Deutsche Feiertage berechnen:

Funktion CalcHolidays() berechnet 17 deutsche Feiertage: Neujahrstag, Hl. Drei Könige, Rosenmontag, Aschermittwoch, Gründonnerstag, Karfreitag, Ostermontag, Maifeiertag, Himmelfahrt, Pfingstmontag, Fronleichnam, Tag der Deut. Einheit, Allerheiligen, Heiligabend, 1. Weihnachtstag, 2. Weihnachtstag und Silvester. Screenshot
//---------------------------------------------------------------------------
//  Funktion CalcHolidays() by http://rad.bytesandmore.de
//---------------------------------------------------------------------------
//  Beschreibung:        Füllt ilDayNoArray-Array mit Werten
//
//  Parameter:           Kalenderjahr, Zeiger auf 17-Elementiges int-Array,
//                       in dem die lfd. Nummern der Tage abgelegt werden
//                       (also z.B. 32 für 1. Februar)
//
//                       Man kann natürlich auch mit TDate/TDateTime arbeiten,
//                       in der uhrsprünglichen Anwendung wurden die Nummern
//                       benötigt, um auf Datensätze zuzugreifen.
//---------------------------------------------------------------------------
void CalcHolidays(short sYear, int* ilDayNoArray)
{
  TDateTime dtFirstDate = TDateTime(sYear, 1, 1);
  TDateTime dtTmpDate;

  // Neujahrstag:
  ilDayNoArray[0] = 1;
  // Hl. Drei Könige:
  ilDayNoArray[1] = 6;

  //-----------------------------------------------------------------
  // Algorhithmus für die Osternberechnung nach Gauß ->
  // gepostet von Wolfgang Weber im Forum der RAD-Seiten am 1.8.02
  //-----------------------------------------------------------------

  // Karfreitag:
  int a, b, c, d, e, m, s, D, M, N, OE;

  a = sYear % 19;
  b = sYear % 4;
  c = sYear % 7;

  m = floor( 8 * floor( sYear/100 ) + 13 ) / 25 - 2;
  s = floor( sYear/100 ) - floor( sYear/400 ) - 2;
  M = ( 15 + s - m ) % 30;
  N = ( 6 + s ) % 7;
  d = ( 19 * a + M ) % 30;
  if ( d == 29 ) D = 28;
  else
  {
    if ( d == 28 && a > 10 ) D = 27;
    else D = d;
  }
  e = ( 2*b + 4*c + 6*D + N ) % 7;

  OE = D + e + 1;
  ilDayNoArray[5] = int(TDateTime(sYear, 3, 21) + OE - dtFirstDate - 1);
  //----------------------------------------

  // Rosenmontag:
  ilDayNoArray[2] = ilDayNoArray[5] - 46;

  // Aschermittwoch:
  ilDayNoArray[3] = ilDayNoArray[5] - 44;

  // Gründonnerstag:
  ilDayNoArray[4] = ilDayNoArray[5] - 1;

  // Ostermontag:
  ilDayNoArray[6] = ilDayNoArray[5] + 3;

  // Maifeiertag:
  dtTmpDate = TDateTime(sYear, 5, 1);
  ilDayNoArray[7] = int(dtTmpDate - dtFirstDate + 1);

  // Himmelfahrt:
  ilDayNoArray[8] = ilDayNoArray[6] + 38;

  // Pfingstmontag:
  ilDayNoArray[9] = ilDayNoArray[6] + 49;

  // Fronleichnam:
  ilDayNoArray[10] = ilDayNoArray[6] + 59;

  // Tag der Deut. Einheit:
  dtTmpDate = TDateTime(sYear, 10, 3);
  ilDayNoArray[11] = int(dtTmpDate - dtFirstDate + 1);

  // Allerheiligen:
  dtTmpDate = TDateTime(sYear, 11, 1);
  ilDayNoArray[12] = int(dtTmpDate - dtFirstDate + 1);

  // Heiligabend:
  dtTmpDate = TDateTime(sYear, 12, 24);
  ilDayNoArray[13] = int(dtTmpDate - dtFirstDate + 1);

  // 1. Weihnachtstag:
  ilDayNoArray[14] = ilDayNoArray[13] + 1;

  // 2. Weihnachtstag:
  ilDayNoArray[15] = ilDayNoArray[14] + 1;

  // Silvester:
  dtTmpDate = TDateTime(sYear, 12, 31);
  ilDayNoArray[16] = int(dtTmpDate - dtFirstDate + 1);
}


Vielen Dank an Wolfgang Weber für die Korrektur der Osterformel !

WoWe schrieb am 1.08.2002 im Forum der RAD-Seiten:

Hallo Serge,

mit dem "Feiertagsberechnungsbeispiel" hab ich mich auch etwas beschäftigt. Die Lösung von Jan Henrik kann man noch etwas verbessern (wenn man will !). Ich habe mehrere Formeln zur Osterberechnung ausprobiert (bezug auf den gregorianischen Kalender), und du kannst ja selber mal prüfen. Über mehrere Jahre ist die Formel nicht korrekt (ok, wenn's einer nicht braucht, aber der Korrektheit halber hier nochmal zum Austesten).
...
void __fastcall TForm1::Formel4BtnClick(TObject *Sender)
{
  int a, b, c, d, e, m, s, D, M, N, OE;
  TDateTime dtTmpDate;

  sYear = StrToInt(StartEdt->Text);
  TDateTime dtFirstDate = TDateTime(sYear, 3, 21);

  a = sYear % 19;
  b = sYear % 4;
  c = sYear % 7;

  m = floor( 8 * floor( sYear/100 ) + 13 ) / 25 - 2;
  s = floor( sYear/100 ) - floor( sYear/400 ) - 2;
  M = ( 15 + s - m ) % 30;
  N = ( 6 + s ) % 7;
  d = ( 19 * a + M ) % 30;
  if ( d == 29 ) D = 28;
  else
    {
     if ( d == 28 && a > 10 ) D = 27;
     else D = d;
    }
  e = ( 2*b + 4*c + 6*D + N ) % 7;

  OE = D + e + 1;

  Wert4Lbl->Caption = IntToStr(OE);
  dtTmpDate = TDateTime(dtFirstDate + OE);
  ShortDateFormat = "dd.mm.yyyy";
  Ostern4Lbl->Caption = DateToStr(dtTmpDate);
}
...

Vielen Dank an Jan Henrik Sylvester für die verbesserte Version der Osterformel:

Von: Jan Henrik Sylvester [mailto:jan_henrik@gmx.net]
Betreff: Vorschlag für C++ Builder Code Snippet "Deutsche Feiertage berechnen"

Großartig, die Formel schon fertig für den C++Builder... aber man muss sie doch auch verstehen können. :-O
Nach einigem Nachdenken habe ich sie in eine Form gebracht, die man wirklich verstehen kann:
// Vollmond Zyklus 1 <= mD <= 29
int mD = (19 * (sYear % 19) + 24) % 30;

// Freitag nach dem 1. Vollmond-Sonntag im Frühling
int mE = ((6 * mD - sYear - sYear / 4 + sYear / 100 - sYear / 400 + 4) % 7 + 7) % 7 + mD + 22;
int mM; if(mE > 31) { mM = 4; mE -= 31; } else mM = 3;
So versteht man, dass alles außer mD nur eine Wochentagskorrektur unter Berücksichtigung der Schaltjahre ist. Außerdem fällt die if() else-Kette weg.

Viele sind sicher nur am Ergebnis interessiert, aber manche würden gerne den Algorithmus verstehen - und auch denen möchte man doch Zeit sparen. ;-)

Viele Grüße,
Jan Henrik Sylvester <me@janh.de>


Ursprünglich verwendeter Algorithmus für die Karfreitag-Berechnung:

//----------------------------------------
// Algorithmus für die Osternberechnung
// portiert aus easter.pas von D. Engler:
//----------------------------------------
// Karfreitag:
int ilA = sYear%19; int ilB = sYear%4; int ilC = sYear%7;
int ilD = (19*ilA+24)%30;
int ilF = 0;

// Jahrhundert-Korrektur:
if(sYear<2500 && sYear>=2300)       ilF = 3;
else if(sYear<2300 && sYear>=2200)  ilF = 2;
else if(sYear<2200 && sYear>=2100)  ilF = 1;
else if(sYear<2100 && sYear>=1900)  ilF = 0;
else if(sYear<1900 && sYear>=1800)  ilF = 6;
else if(sYear<1800 && sYear>=1700)  ilF = 5;
else if(sYear<1700)                 ilF = 4;

int ilE = (2*ilB + 4*ilC + 6*ilD + 5 + ilF)%7;
ilE = 22 + ilD + ilE;
int ilM = 3; if (ilE > 31) {ilM = 4; ilE = ilE - 31;}

//----------------------------------------
dtTmpDate = TDateTime(sYear, short(ilM), short(ilE));
ilDayNoArray[5] = int(dtTmpDate - dtFirstDate - 1);


  Download BCB6
Projekt-Quellcode
Download
Demo-Exe

© '99-2003 by S. Kreutzmann