5 unsigned char is_leap(const unsigned int year)
7 // Die Regel lautet: Alles, was durch 4 teilbar ist, ist ein Schaltjahr.
8 // Es sei denn, das Jahr ist durch 100 teilbar, dann ist es keins.
9 // Aber wenn es durch 400 teilbar ist, ist es doch wieder eins.
11 if ((year % 400) == 0)
13 else if ((year % 100) == 0)
15 else if ((year % 4) == 0)
21 unsigned short days_of_month(const unsigned int uMonat, const unsigned int uJahr)
23 // ungült,Jan,Feb,Mrz,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez
24 int arrTageImMonat[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
27 // Februar: Schaltjahr unterscheiden
34 if ((uMonat >= 1) && (uMonat <= 12))
35 return arrTageImMonat[uMonat];
41 short getAnzahlTageImJahr(const unsigned int uJahr)
43 return (is_leap(uJahr)) ? 366 : 365;
46 short getWochentag(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
48 // ungült Jan Feb Mrz Apr Mai Jun Jul Aug Sep Okt Nov Dez
49 unsigned char arrMonatsOffset[13] = { 0, 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
52 // Monat / Tag - Plausi prüfen:
53 if ((uTag > 31) || (uMonat > 12) || (uMonat <= 0)
54 || (uTag <= 0) || (uJahr <= 0)) {
58 unsigned char cbTagesziffer = (uTag % 7);
59 unsigned char cbMonatsziffer = arrMonatsOffset[uMonat];
60 unsigned char cbJahresziffer = ((uJahr % 100) + ((uJahr % 100) / 4)) % 7;
61 unsigned char cbJahrhundertziffer = (3 - ((uJahr / 100) % 4)) * 2;
63 // Schaltjahreskorrektur:
64 if ((uMonat <= 2) && (is_leap(uJahr)))
65 cbTagesziffer = cbTagesziffer + 6;
67 nErgebnis = (cbTagesziffer + cbMonatsziffer + cbJahresziffer + cbJahrhundertziffer) % 7;
80 short getTagDesJahres(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
82 // Der wievielte Tag des Jahres ist dieser Tag
83 if ((uMonat == 0) || (uMonat > 12)) {
87 unsigned int uLokalTag = uTag;
88 unsigned int uLokalMonat = uMonat;
90 while (uLokalMonat > 1) {
92 uLokalTag += days_of_month(uLokalMonat, uJahr);
98 short getKalenderwoche(short uTag, short uMonat, short uJahr)
100 // Berechnung erfolgt analog DIN 1355, welche besagt:
101 // Der erste Donnerstag im neuen Jahr liegt immer in der KW 1.
102 // "Woche" ist dabei definiert als [Mo, ..., So].
103 short nTagDesJahres = getTagDesJahres(uTag, uMonat, uJahr);
105 // Berechnen des Wochentags des 1. Januar:
106 short nWochentag1Jan = getWochentag(1, 1, uJahr);
108 // Sonderfälle Freitag und Samstag
109 if (nWochentag1Jan >= 5)
110 nWochentag1Jan = nWochentag1Jan - 7;
112 // Sonderfälle "Jahresanfang mit KW - Nummer aus dem Vorjahr"
113 if ( (nTagDesJahres + nWochentag1Jan) <= 1) {
114 return getKalenderwoche(31, 12, uJahr - 1);
117 short nKalenderWoche = ((nTagDesJahres + nWochentag1Jan + 5) / 7);
119 // 53 Kalenderwochen hat grundsätzlich nur ein Jahr,
120 // welches mit einem Donnerstag anfängt !
121 // In Schaltjahren ist es auch mit einem Mittwoch möglich, z.B. 1992
122 // Andernfalls ist diese KW schon die KW1 des Folgejahres.
123 if (nKalenderWoche == 53) {
124 boolean bIstSchaltjahr = is_leap(uJahr);
126 if ((nWochentag1Jan == 4) // Donnerstag
127 || (nWochentag1Jan == -3) // auch Donnerstag
128 || ((nWochentag1Jan == 3) && bIstSchaltjahr)
129 || ((nWochentag1Jan == -4) && bIstSchaltjahr)) {
130 ; // Das ist korrekt und erlaubt
132 nKalenderWoche = 1; // Korrektur des Wertes
135 return nKalenderWoche;
138 void getOsterdatum(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
140 // Berechnet für ein beliebiges Jahr das Osterdatum.
142 // Quelle des Gauss - Algorithmus: Stefan Gerth,
143 // "Die Gauß'sche Osterregel", Nürnberg, Februar 2003.
144 // http://krapfen.org/content/paper/Schule/Facharbeit/Berechnung_des_Osterfestes.pdf
146 unsigned int a = uJahr % 19;
147 unsigned int b = uJahr % 4;
148 unsigned int c = uJahr % 7;
152 int p = ((8 * k) + 13) / 25;
153 unsigned int Egz = (38 - (k - q) + p) % 30; // Die Jahrhundertepakte
154 unsigned int M = (53 - Egz) % 30;
155 unsigned int N = (4 + k - q) % 7;
157 unsigned int d = ((19 * a) + M) % 30;
158 unsigned int e = ((2 * b) + (4 * c) + (6 * d) + N) % 7;
160 // Ausrechnen des Ostertermins:
161 if ((22 + d + e) <= 31) {
168 // Zwei Ausnahmen berücksichtigen:
171 else if ((*uTag == 25) && (d == 28) && (a > 10))
175 // Offsets für andere Feiertage:
177 // Schwerdonnerstag / Weiberfastnacht -52
179 // Fastnachtsdienstag -47
180 // Aschermittwoch -46
185 // Christi Himmelfahrt +39
186 // Pfingstsonntag +49
190 // Mariä Himmelfahrt ist stets am 15. August (Danke an Michael Plugge!)
193 void getViertenAdvent(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
195 // Berechnet für ein beliebiges Jahr das Datum des 4. Advents-Sonntags.
196 // Der 4. Adventssonntag ist stets der Sonntag vor dem 1. Weihnachtsfeiertag,
197 // muß also stets in der Periode [18. - 24.12.] liegen:
199 *uMonat = 12; // Das steht jedes Jahr fest :-)
201 short nWoTag = getWochentag(24, 12, uJahr); // Wochentag des 24.12. ermitteln
205 // Offsets: Der Buß- und Bettag liegt stets 32 Tage vor dem 4. Advent