Hilfe bei Python-Programm (Wochentag eines Datum bestimmen)?
Ich weiß nicht was ich falsch gemacht habe, kann mir jemand den Fehler in meinem Programm nennen?:
def main():
day = int(input("Day: "))
month = int(input("Month: "))
year = int(input("Year: "))
print(day_name(day, month, year))
def day_name(day, month, year):
months = {1 : 0,
2 : 31,
3 : 59,
4 : 90,
5 : 120,
6 : 151,
7 : 181,
8 : 212,
9 : 243,
10 : 273,
11 : 304,
12 : 334}
days_m = 0
if month in months:
days_m = int(months[month])
days_y = 0
for y in range(year ):
if (y % 4 == 0 and y % 100 != 0) or y % 400 == 0:
days_y += 366
else:
days_y += 365
complete_days = int(day) + int(days_m) + int(days_y)
if int(complete_days) % 7 == 0:
return "Sunday"
elif int(complete_days) % 7 == 1:
return "Monday"
elif int(complete_days) % 7 == 2:
return "Tuesday"
elif int(complete_days) % 7 == 3:
return "Wednesday"
elif int(complete_days) % 7 == 4:
return "Thursday"
elif int(complete_days) % 7 == 5:
return "Friday"
elif int(complete_days) % 7 == 6:
return "Saturday"
main()
Dass ich hier was nicht falsch verstehe, es ist deine Aufgabe das so zu machen? Weil ich würde hier einfach die Datetime bibliothek bzw. Calendar-Bibliothek benutzen.
Genau ich soll eine eigenes Programm dafür schreiben.
6 Antworten
Zum Einen zählst Du alle Tage seit dem 0. Januar 0. Wäre das wirklich ein Sonntag gewesen? Wenn nicht, musst Du noch einen konstanten Offset zu complete_days addieren.
Zum Anderen zählst Du jedes Jahr als Schaltjahr, auch wenn das gegebene Datum vor dem 1. März liegt.
Noch ein kleiner Tipp:
Mit weekdays = ("Sunday", "Monday", ...) kannst Du die lange if-else-Kette am Ende streichen. Schreibe einfach:
return weekdays[complete_days % 7]
Ich möchte Dir den Spaß am Basteln nicht verderben.
Der Trick bei der Sache ist, unseren (ziemlich unregelmäßigen) Grergorianischen Kalender in die Julianische Tageszählung umzuwandeln.
Dafür gibt es eine recht "einfache" Formel:
JulianDay = (1461 * (Year + 4800 + (Month − 14)/12))/4 +(367 * (Month − 2 − 12 * ((Month − 14)/12)))/12 − (3 * ((Year + 4900 + (Month - 14)/12)/100))/4 + Day − 32075
Das sieht erstmal ziemlich konfus aus. Damit hast Du eine lineare Zählung der Tage seit 1. Januar des Jahres 4713 v. Chr
...lass uns obiges Monstrum mal in eine etwas übersichtlichere Pythonfunktion überführen.
def gregorian_to_julian(year, month, day):
i = int((month - 14) / 12)
jd = day - 32075
jd += int((1461 * (year + 4800 + i)) / 4)
jd += int((367 * (month - 2 - (12 * i))) / 12)
jd -= int((3 * int((year + 4900 + i) / 100)) / 4)
return jd
Aufruf:
>>> gregorian_to_julian(1970, 1, 1)
2440588
Ein solche lineare Zählung brauchst du dann nur noch via mod 7 in den jeweiligen Wochentag justieren...
Tipp der 1.1.1970 war ein Donnerstag und 2440588 %7 =3
Du vergisst, dass in Schaltjahren der Schalttag vor dem 1 März unberücksichtigt bleiben muss. Bzw. weil die Range-Funktion bei 0 anfängt und 1 vor ihrem Argument aufhört, dass sich in einem Schaltjahr der Schalttag ab dem 1. März eine Rolle spielt.
Du beginnst beim Jahr 0 an zu zählen.
(Exkurs: das Jahr 0 existiert eigentlich nicht, es wäre das Jahr 1 v.Chr. - was zu einem weiteren Eins-daneben-Fehler führt.)
Die Ermittlung des Wochentags funktioniert auf diese Weise auch nur, wenn der 00.01.0000 zufällig ein Sonntag war. Sonst musst du entsprechend verschieben.
(Warum nimmst du nicht [int(complete_days) % 7] als Index eines Arrays?)
noch besser ist der 1.Janur 4713 vChr.
da gibt es eine Formel von der Stange....
lol – zwei Nutzer, ein Gedanke. Aber ich war diesmal 9 Sekunden schneller :-P
Und das, obwohl ich davor erst den Code in der Frage formatiert habe.
Aus diesem Teil
if month in months:
days_m = int(months[month])
days_y = 0
for y in range(year ):
if (y % 4 == 0 and y % 100 != 0) or y % 400 == 0:
days_y += 366
else:
days_y += 365
mach diesen:
days_m = months[month]
if ((year % 4 == 0 and year % 100 != 0) or year % 400 == 0) and month > 2:
days_m += 1
days_y = 0
for y in range(1,year):
if (y % 4 == 0 and y % 100 != 0) or y % 400 == 0:
days_y += 366
else:
days_y += 365
Erläuterung:
Die Abfrage "if month in months" ist überflüssig, wenn du anschließend den Fehler (dass month nicht 1..12 ist) nicht behandelst. Du prüfst ja ansonsten auch nicht die Gültigkeit des Datums (z.B. day=40 oder day=31 und month=4)
Danach schiebe in Schaltjahren nach Ende Februar einen zusätzlichen Schalttag ein.
for y in range(1,year)
Zähle die Jahre ab 1 zusammen, nicht ab 0. Alternativ: starte mit days_y = -2
Dann passt's
Zunächst einmal wäre es doch hilfreich (insbesondere bei Python, wo es doch auch auf die Einrückungen ankommt), wenn du den Code ordentlich formatiert hier in deine Frage einfügen würdest. Dazu gibt es einen entsprechende Schaltfläche...
Des Weiteren möchte ich dich darauf hinweisen, dass es doch bereits quasi fertige Lösungen dazu im datetime-Modul gibt:
https://docs.python.org/3/library/datetime.html#datetime.date.weekday
https://docs.python.org/3/library/datetime.html#datetime.date.isoweekday
Aber evtl. wolltest du das ja trotzdem einfach als Übung mal selbst probieren. Ich versuche gleich mal deinen Code (mit den kaum sichtbaren Einrückungen) zu entziffern, und zu schauen, wo das Problem liegt.

Soweit ich das sehe, gibt es zwei relativ einfache Fehler...
- Du prüfst zwar bei der Zählung der days_y auf Schaltjahre. Aber du prüfst nicht, ob in dem Zieljahr ein Schaltjahr vorliegt. Dementsprechend ist in Schaltjahren dein days_m ab dem 1. März um 1 daneben.
- Des Weiteren scheinst du davon ausgegangen zu sein, dass am 01.01.0001 mit einem Montag zu rechnen sei. Aber am 01.01.0001 müsste rechnerisch tatsächlich ein Mittwoch sein.
Letztendlich führen diese beiden Fehler dazu, dass du...
- in Schaltjahren ab dem 1. März um einen Wochentag daneben liegst.
- in Schaltjahren vor dem 1. März und in Nicht-Schaltjahren um zwei Wochentage daneben liegst.