5 unsigned char is_leap(const unsigned int year)
7 /* the rule is, everything that can be devided by 4 is leap.
8 * Exception: the year can be devided by 100, then it is not,
9 * except it canbe devided by 400, then it is again.
12 if ((year % 400) == 0)
14 else if ((year % 100) == 0)
16 else if ((year % 4) == 0)
22 unsigned short days_of_month(const unsigned int uMonat, const unsigned int uJahr)
24 // invalid,January,Febuary,March,April,May,June,July,August,September,October,November,December
25 int arrTageImMonat[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
28 // Febuary: distinguish leap
35 if ((uMonat >= 1) && (uMonat <= 12))
36 return arrTageImMonat[uMonat];
42 short getAnzahlTageImJahr(const unsigned int uJahr)
44 return (is_leap(uJahr)) ? 366 : 365;
47 short getWochentag(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
49 // ungült Jan Feb Mrz Apr Mai Jun Jul Aug Sep Okt Nov Dez
50 unsigned char arrMonatsOffset[13] = { 0, 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
53 // Monat / Tag - Plausi prüfen:
54 if ((uTag > 31) || (uMonat > 12) || (uMonat <= 0)
55 || (uTag <= 0) || (uJahr <= 0)) {
59 unsigned char cbTagesziffer = (uTag % 7);
60 unsigned char cbMonatsziffer = arrMonatsOffset[uMonat];
61 unsigned char cbJahresziffer = ((uJahr % 100) + ((uJahr % 100) / 4)) % 7;
62 unsigned char cbJahrhundertziffer = (3 - ((uJahr / 100) % 4)) * 2;
64 // Schaltjahreskorrektur:
65 if ((uMonat <= 2) && (is_leap(uJahr)))
66 cbTagesziffer = cbTagesziffer + 6;
68 nErgebnis = (cbTagesziffer + cbMonatsziffer + cbJahresziffer + cbJahrhundertziffer) % 7;
81 short getTagDesJahres(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
83 // Der wievielte Tag des Jahres ist dieser Tag
84 if ((uMonat == 0) || (uMonat > 12)) {
88 unsigned int uLokalTag = uTag;
89 unsigned int uLokalMonat = uMonat;
91 while (uLokalMonat > 1) {
93 uLokalTag += days_of_month(uLokalMonat, uJahr);
99 short getKalenderwoche(short uTag, short uMonat, short uJahr)
101 // Berechnung erfolgt analog DIN 1355, welche besagt:
102 // Der erste Donnerstag im neuen Jahr liegt immer in der KW 1.
103 // "Woche" ist dabei definiert als [Mo, ..., So].
104 short nTagDesJahres = getTagDesJahres(uTag, uMonat, uJahr);
106 // Berechnen des Wochentags des 1. Januar:
107 short nWochentag1Jan = getWochentag(1, 1, uJahr);
109 // Sonderfälle Freitag und Samstag
110 if (nWochentag1Jan >= 5)
111 nWochentag1Jan = nWochentag1Jan - 7;
113 // Sonderfälle "Jahresanfang mit KW - Nummer aus dem Vorjahr"
114 if ( (nTagDesJahres + nWochentag1Jan) <= 1) {
115 return getKalenderwoche(31, 12, uJahr - 1);
118 short nKalenderWoche = ((nTagDesJahres + nWochentag1Jan + 5) / 7);
120 // 53 Kalenderwochen hat grundsätzlich nur ein Jahr,
121 // welches mit einem Donnerstag anfängt !
122 // In Schaltjahren ist es auch mit einem Mittwoch möglich, z.B. 1992
123 // Andernfalls ist diese KW schon die KW1 des Folgejahres.
124 if (nKalenderWoche == 53) {
125 boolean bIstSchaltjahr = is_leap(uJahr);
127 if ((nWochentag1Jan == 4) // Donnerstag
128 || (nWochentag1Jan == -3) // auch Donnerstag
129 || ((nWochentag1Jan == 3) && bIstSchaltjahr)
130 || ((nWochentag1Jan == -4) && bIstSchaltjahr)) {
131 ; // Das ist korrekt und erlaubt
133 nKalenderWoche = 1; // Korrektur des Wertes
136 return nKalenderWoche;
139 void getOsterdatum(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
141 // Berechnet für ein beliebiges Jahr das Osterdatum.
143 // Quelle des Gauss - Algorithmus: Stefan Gerth,
144 // "Die Gauß'sche Osterregel", Nürnberg, Februar 2003.
145 // http://krapfen.org/content/paper/Schule/Facharbeit/Berechnung_des_Osterfestes.pdf
147 unsigned int a = uJahr % 19;
148 unsigned int b = uJahr % 4;
149 unsigned int c = uJahr % 7;
153 int p = ((8 * k) + 13) / 25;
154 unsigned int Egz = (38 - (k - q) + p) % 30; // Die Jahrhundertepakte
155 unsigned int M = (53 - Egz) % 30;
156 unsigned int N = (4 + k - q) % 7;
158 unsigned int d = ((19 * a) + M) % 30;
159 unsigned int e = ((2 * b) + (4 * c) + (6 * d) + N) % 7;
161 // Ausrechnen des Ostertermins:
162 if ((22 + d + e) <= 31) {
169 // Zwei Ausnahmen berücksichtigen:
172 else if ((*uTag == 25) && (d == 28) && (a > 10))
176 // Offsets für andere Feiertage:
178 // Schwerdonnerstag / Weiberfastnacht -52
180 // Fastnachtsdienstag -47
181 // Aschermittwoch -46
186 // Christi Himmelfahrt +39
187 // Pfingstsonntag +49
191 // Mariä Himmelfahrt ist stets am 15. August (Danke an Michael Plugge!)
194 void getViertenAdvent(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
196 // Berechnet für ein beliebiges Jahr das Datum des 4. Advents-Sonntags.
197 // Der 4. Adventssonntag ist stets der Sonntag vor dem 1. Weihnachtsfeiertag,
198 // muß also stets in der Periode [18. - 24.12.] liegen:
200 *uMonat = 12; // Das steht jedes Jahr fest :-)
202 short nWoTag = getWochentag(24, 12, uJahr); // Wochentag des 24.12. ermitteln
206 // Offsets: Der Buß- und Bettag liegt stets 32 Tage vor dem 4. Advent