Hilfe bei Python-Programm (Wochentag eines Datum bestimmen)?

Valentin1720653  04.05.2024, 17:42

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.

JakobAT 
Beitragsersteller
 04.05.2024, 17:49

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?)

Woher ich das weiß:Berufserfahrung – Software-Entwickler

ralphdieter  04.05.2024, 18:26

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.

0
Erzesel  04.05.2024, 19:29

noch besser ist der 1.Janur 4713 vChr.

da gibt es eine Formel von der Stange....

0

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...

Bild zum Beitrag

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.

 - (programmieren, Code, Python)

mihisu  04.05.2024, 18:20

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.
2