Funktion zur Berechnung des Wochentages
-
Bin gerade über diese Funktion gestolpert:
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.25; 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 && (month < 2 || (month == 2 && day <= 28))) { day--; } return (day%7+1); }
So richtig elegant sieht das noch nicht aus. Vielleicht hat jemand eine bessere Idee, wie man das kompakt lösen kann.
-
-
Das sieht ja noch schrecklicher aus.
-
Ist aber korrekt (im Gegensatz zu obiger Funktion)
-
Kannst du das nach C übersetzen mit obigen Parametern?
Hier im Forum gefunden:
dayofweek(int y, int m, int d) /* 0 = Sonntag */ /* 1 <= m <= 12, y > 1752 oder so */ { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; }
im Gegensatz zu obiger Funktion
Bisher wurde der Wochentag korrekt berechnet, aber ich traue der sache auch nicht.
-
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.