Funktion zur Berechnung des Wochentages
-
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.
-
Ich weiß schon, weshalb ich bei Dir nicht mitspiele.
Eigentlich schade. Mit dir als Math Geek könnte das richtig gut werden, aber wir schaffen das auch so. Ist sowieso mehr Praxis als Theorie.
Diese Wochentag-Formel ist ursprünglich nicht von mir, ich wollte sie nur verfeinern oder zumindest korrekt machen.
Entscheidend ist, dass der korrekte Tag heraus kommt, und das klappt nun.
-
Erhard Henkes schrieb:
Wir nehmen aber Volkard's Zahl, weil die nachvollziehbar ist (wenn sie auch nicht stimmt)
Sie stimmt natürlich, weil der gregorianische Kalender abgebildet werden soll und nichts anderes.
Naja, Du hattest die richtige Zahl schon in der Hand: 146097.0/400.0=365.2425
-
OK, dann nehmen wir den Bruch. Dann ist neuer_user auch zufrieden.
static uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { day += 6; // 1.1.2000 was a saturday day += (year-2000) * 146097.0/400.0 + days[month-1]; if (isLeapyear(year) && (month < 2 || (month == 2 && day <= 28))) { day--; } return ( day % 7 + 1 ); }
-
Ich finde, dass sich diese Formel nun sehen lassen kann. Wenn man im Datum zurück geht, kann man diese nun sicher auch ab 1980 einsetzen.
-
Da sich der Kalender alle 400 Jahre wiederholt, kannste statt j-2000 auch j-1600 schreiben. Oder j-0.
-
Danke für den Hinweis. Mit meinem Win XP SP3 kann ich nur von 1.1.1980 bis 31.12.2099 experimentell mit VBox testen. Qemu macht die Grätsche (schwach gebastelt), und GNU GCC versagt beim Compilieren, wenn die Zeit aus den Fugen ist.
Habe gerade bei meinem Sohn Win 7 gecheckt, selber Murks: 1980 - 2099.
-
http://www.thkoehler.de/midnightblue/m_kal.htm
Volkard hat Recht. 1.1.1600 ist ein Samstag.
@Volkard: 0 ist allerdings nicht brauchbar wegen dem 15.10.1582 (Beginn der gregorianischen Zeitrechnung). Da hat der gute Gregor 10 Tage ausgelassen (4.10. ==> 15.10.1582 ).
-
Erhard Henkes schrieb:
@Volkard: 0 ist allerdings nicht brauchbar wegen dem 15.10.1582 (Beginn der gregorianischen Zeitrechnung). Da hat der gute Gregor 10 Tage ausgelassen (4.10. ==> 15.10.1582 ).
Doch.
Es geht immernoch nur darum, den gregorianischen Kalender abzubilden. Für Eingaben nach dem 15.10.1582 klappt doch alles mit j-0.
-
Hast Recht.
// Gregorian calender started 15th October 1582 static uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { day += 6; // 1.1.1600 was a saturday day += (year/*-1600*/) * 146097.0/400.0 + days[month-1];
So könnte man das evtl. machen, damit Theorie und Praxis zu ihrem Recht kommen.
-
Sogar
day += 6; // 1.1.0 was a saturday
wobei hier das "was" nicht "war", sondern "wäre" heißt, wenn es da den greg Kalender schon gegeben hätte und wenn es ein Jahr 0 gäbe.
Ich würde einfach alle gregorianisch lassen. Daten vorher werden halt falsch berechnet. Muß ins User-Handbuch.
-
Jetzt muss ich dich in die Schranken weisen.
Das ist ja ein Denken wie bei "1984".So machen wir es, damit wir die Zeit vor 2000 auch korrekt abdecken:
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)); } // Gregorian calender started 15th October 1582 static uint8_t calculateWeekday(uint16_t year, uint8_t month, int32_t day) { day += 6; // 1.1.1600 was a saturday day += (year/*-1600*/) * 146097.0/400.0 + days[month-1]; if (isLeapyear(year) && (month < 2 || (month == 2 && day <= 28))) { day--; } return ( day % 7 + 1 ); }
-
Aber ich glaube, es wird doch
static uint8_t calculateWeekday(uint16_t year, uint8_t month, int8_t day){ return (calculateDaysFromDate(year,month,day)+3)%7; }
Man will ja auch die Differenz zwischen zwei Daten ausrechnen können. DIe +3 ist geraten. Das %7, damit Tage bei 0 beginnen wie rechtschaffene enums und Arrayindizes.
-
@Volkard: vielen Dank!
http://www.c-plusplus.net/forum/p2139077#2139077Hier sieht man sehr schön die Repetition:
http://de.wikipedia.org/w/index.php?title=Datei:Ewiger_Kalender_gregorianisch.svg&filetimestamp=20110916201156
-
Oder so: Die Schaltjahre wiederholen sich alle 400 Jahre.
Diese 400 Jahre haben 365.2425*400=146097 Tage.
Und 146097 ist zufällig durch 7 teilbar.
-
Right Sir!