Funktion zur Berechnung des Wochentages
-
Erhard Henkes schrieb:
Bisher wurde der Wochentag korrekt berechnet, aber ich traue der sache auch nicht.
Im Jahr 2100 stimmts nimmer, soweit ich das sehen kann, das ist nämlich kein Schaltjahr
-
ich hab mal so angefangen:
EDIT: (angefangen heißt nicht fertig )
EDIT2: ist auch irgendwie falschstatic uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { //1.1.2000 was Saturday size_t day_ = 0; int32_t diff_day = 1-day; int32_t diff_year = 2000-year; uint8_t schaltjahr[diff_year+1]; for(int i = 0;i < diff_year+1;i++) { if((2000+i)%4 == 0 && ((2000+i)%100 != 0 || (2000+i)%400 == 0)) schaltjahr[i] = 1; else schaltjahr[i] = 0; } if(diff_year > 0) { for(int i = 0;i < diff_year;i++) { day_ += 365+schaltjahr[i]; } } }
-
da kommt noch kein Wochentag zurück ^^
-
Es ist interessant, wenn man höhere Jahreszahlen mit Emulatoren oder Windows testen will:
- qemu bricht sofort beim Start zusammen (ganz erbärmlich)
- Datum/Zeit von Win XP endet im Jahr 2099 (Unverschämtheit!)
- der GNU-Compiler gerät aus dem Takt, wenn man 2099 einstellt (merkwürdig)
-
static uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { //1.1.2000 was Saturday size_t day_ = 5; int32_t diff_year = year-2000; uint8_t schaltjahr[diff_year+1]; //calculate Schaltjahre for(int i = 0;i < diff_year+1;i++) { if((2000+i)%4 == 0 && ((2000+i)%100 != 0 || (2000+i)%400 == 0)) schaltjahr[i] = 1; else schaltjahr[i] = 0; } //add days of diff. of years if(diff_year > 0) { for(int i = 0;i < diff_year;i++) { day_ += 365+schaltjahr[i]; } } //Month if(month > 1) { for(int i = 0;i < month-1;i++) { if(month-1+i == 2) { if(schaltjahr[year]) day_ += 29; else day_ += 28; } else { if((month-1+i)%2 == 1) day_ += 31; else day_ += 30; } } } //add diff.day day_ += day-1; return day_%7; }
Ich hab das noch nicht überprüft aber bei Montag sollte 0 rauskommen
-
Im Jahr 2100 stimmts nimmer, soweit ich das sehen kann, das ist nämlich kein Schaltjahr
Das lässt sich leicht ausbügeln:
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) && (month < 2 || (month == 2 && day <= 28))) { day--; }
-
Ja, aber du hast doch sowieso schon eine fertige Implementierung der Wochentagsformel gefunden!? Ich würd die benutzen^^
-
jetzt hab ich mir mühe gemacht
-
Wenn man unsere Formel optisch etwas pusht, die korrekte isLeapyear(...) einsetzt und die korrekte Zahl der Tage pro Jahr verwendet, dann hat das auch etwas Eingängliches.
uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { day += 6; // 1.1.2000 was a saturday day += (year-2000) * 365.24219; if (month > 11) day+=334; else if (month > 10) day+=304; else if (month > 9) day+=273; else if (month > 8) day+=243; else if (month > 7) day+=212; else if (month > 6) day+=181; else if (month > 5) day+=151; else if (month > 4) day+=120; else if (month > 3) day+=90; else if (month > 2) day+=59; else if (month > 1) day+=31; if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) && (month < 2 || (month == 2 && day <= 28))) { day--; } return ( day % 7 + 1 ); }
@dot: Diese perfekte Formel von Gauß versteht man nicht leicht. Es gibt übrigens noch mehr Systeme zur Berechnung.
@neuer_user: Vielleicht nehmen wir auch deine Formel. Noch ist alles offen.
-
Erhard Henkes schrieb:
Diese perfekte Formel versteht man nicht. Es gibt übrigens noch mehr Systeme zur Berechnung.
Was genau versteht man daran nicht, im Wikipedia-Artikel ist doch eine komplette Herleitung!?
-
Welche Formel wir verwenden werden, entscheidet letztendlich das Team. Der Thread ist noch zu frisch. Danke auf jeden Fall für den Tipp.
-
Meine Version ist länger.
Mich stört diese Kommaangabe(year-2000) * [u]365.24219[/u];
-
Ja, das stimmt. Man könnte vielleicht auch 146097.0 / 400.0 verwenden.
Wenn wir eine kürzere Formel für month ==> day finden, ist unsere Formel viel schöner. Sie muss ja nur ab 2000 und nicht vorher gelten.
- isLeapyear(...) könnte man auslagern
- die Zahlen der Tage für einen abgeschlossenen Monat könnte man in ein Array packen
-
Erhard Henkes schrieb:
Sie muss ja nur ab 2000 und nicht vorher gelten.
So haben schon viele gedacht...
-
static uint16_t days[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; static bool isLeapyear(uint16_t year) { return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); } static uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { day += 6; // 1.1.2000 was a saturday day += (year-2000) * 365.24219 + days[month-1]; if (isLeapyear(year) && (month < 2 || (month == 2 && day <= 28))) { day--; } return ( day % 7 + 1 ); }
So sieht das doch schon richtig fein aus.
Verflixt! beim 31.12.2099 kommt Mittwoch raus, ist aber Donnerstag. Die genaue Kommazahl ist offenbar nicht hilfreich. Nein, daran liegt es nicht.
-
Erhard Henkes schrieb:
Verflixt! beim 31.12.2099 kommt Mittwoch raus, ist aber Donnerstag. Die genaue Kommazahl ist offenbar nicht hilfreich. Nein, daran liegt es nicht.
Woher kommt die 365.24219?
-
von hier: http://de.wikipedia.org/wiki/Schaltjahr#Gregorianischer_Kalender
astronomisch: 365,24219
-
Sag mir nicht, daß Du da einfach das tropische Jahr aus dem Lexikon kopiert hast. Das darf ja nicht wahr sein.
Jedes Jahr hat 365 Tage. 365
Jedes vierte hat einen Tag mehr. +0.25
Jedes hundertste einen Tag weniger. -0.01
Jedes vierhundertste einen mehr. +0.0025
sind für mich 365.2425Erhard schrieb:
146097.0 / 400.0
Ach nööö!
-
Ich denke, es liegt daran, dass ich bei dem falsch eingestellten Datum kompiliert habe. Nach rebuild in 2011 klappt es wieder.
Die Zahl dort ist nicht entscheidend, ob 365.2419, 365.2425 oder 365.25
Wir nehmen aber Volkard's Zahl, weil die nachvollziehbar ist (wenn sie auch nicht stimmt):
static uint16_t days[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; static bool isLeapyear(uint16_t year) { return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); } static uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { day += 6; // 1.1.2000 was a saturday day += (year-2000) * 365.2425 + days[month-1]; if (isLeapyear(year) && (month < 2 || (month == 2 && day <= 28))) { day--; } return ( day % 7 + 1 ); }
31.12.2099 ist ein Donnerstag! yep.
-
Ich weiß schon, weshalb ich bei Dir nicht mitspiele.