Format Date

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Davidcopperfield
User
Beiträge: 8
Registriert: Freitag 12. November 2021, 22:15

Schreiben Sie eine Funktion format_date, die 3 Parameter benötigt:

Tag: Tag,
Monat: Monat,
Jahr: Jahr.
Die Funktion sollte prüfen, ob das Datum korrekt ist:

Monat sollte innerhalb von (1, 12) liegen,
der Tag darf nicht größer als 30 - 31 sein (oder 28 im Falle des Februars, bei Schaltjahren wird die Prüfung übersprungen).
Wenn eine der Bedingungen nicht auf den Kalender zutrifft, sollte die Funktion None zurückgeben.

Die Funktion sollte einen formatierten Textstring im Format "Tag Monat Jahr" zurückgeben.

Beispiel
d = format_date(12, 1, 2017)
print(d)

12. Januar 2017

d = format_date(12, 13, 2017)
print(d)

None

Code: Alles auswählen

dayy = int(input("Tag eingeben : "))
monthh = int(input("Monat  eingeben : "))
yearr = int(input("Jahr eingeben : "))

def format_date(dayy, monthh, yearr):

    for xxd in range(1,32):
        if type(dayy) != int:
            break
            return("None")

    for xxm in range(1,13):
        if monthh == 2 and dayy in range(1, 29):  #February must be within 1 and 28 in this case
            continue
        else:
            break
        return ("None")

        if type(monthh) != int:
            return ("None")
            break
        if type(yearr) != int:
            return("None")
            break

print(format_date(dayy, monthh, yearr))

Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Ich sehe keine Frage in deinem Beitrag.

Zum Code:
Klemmen deine Tasten? Oder warum hast du so gruselige Namen verwendet? Die Doppelung des letzten Buchstaben ist ebenso überflüssig wie das Vorwegstellen von zwei x.
Verwende vernünftige, sprechende Namen.

Was versuchst du denn da mit range? Warum willst du über Zahlenreihen iterieren? Mal ganz abgesehen, dass du die Variable nicht verwendest, an die du die Elemente bindest ist das an dieser Stelle auch falsch. Du möchtest prüfen ob eine Zahl zwischen bestimmten Werten ist. Wie stellt man das denn in der Mathematik dar?

Ein break nach einem Return macht keinen Sinn. Ein return beendet die Funktion, das break wird nie erreicht.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum wiederholst Du immer den letzten Buchstaben Deiner Variablennamen? Variablennamen sollen den Leser nicht rätseln lassen. Genauso ist xxd oder xxm schlecht, weil niemand weiß, wofür xx steht und d die Abkürzung für day einfach auch nur das Lesen erschwert, ohne Dir wirklich Arbeit beim Schreiben zu sparen.
Die for-Schleife macht nichts mit xxd, so dass nur 31mal das selbe geprüft wird, nämlich ob der Typ der Variable dayy ein int ist. Ist das nicht der Fall, passiert aber auch nichts, denn per break wird einfach nur die Schleife verlassen.
In der zweiten Schleife mußt Du Dir auch die if-Bedingung und die Reaktion dann genau anschauen. Es gibt den Fall dass wir Februar haben und der Tag im Bereich 1 bis 28 liegt, dann fängt die Schleife wieder von vorne an (continue) und prüft das selbe noch 11 weitere Male, bevor die Schleife ohne weitere Reaktion endet, oder die Bedingung ist nicht wahr, dann wird die Schleife per break verlassen. In beiden Fällen wird wieder nichts mit xxm gemacht und der Rest der Schleife wird nie erreicht.

Daneben gibt es noch ein paar Bemerkungen: `return` verläßt sofort die Funktion, alles was danach steht wird also nie erreicht. `return` ist keine Funktion, die Klammern verwirren also nur. Laut Aufgabenbeschreibung soll der Wert None zurückgeliefert werden, nicht der String "None". Auf Typen prüft man in Python normalerweise nicht explizit, das passiert schon implizit, wenn z.B. versucht wird einen String "1" >= 1 zu prüfen. Falls doch, benutzt man isinstance statt type.

Zum Grundsätzlichen:
Wenn man eine Funktion schreibt, fängt man nicht an und schreibt irgendetwas zusammen und hofft am Schluß dass es komplett funktioniert, sondern man entwickelt eine Funktion Schritt für Schritt
So ist ja auch die Aufgabenstellung geschrieben, dass man sie Satz für Satz abarbeiten kann und für jeden Satz, den man implementiert hat, dann die Funktion ausführlich testet, indem man Tests schreibt, die ausgeführt werden können und damit die Richtigkeit der Funktion testen.
Der erste Satz sagt, welche Argumente die Funktion haben soll. Soweit hast Du das richtig umgesetzt.
Der zweite Satz sagt, dass der Monat innerhalb von 1 bis 12 liegen soll.
Dafür schreibe ich Dir mal die Funktion, dass Du weißt, wie Du weiter vorgehen kannst:

Code: Alles auswählen

def format_date(day, month, year):
    if not (1 <= month <= 12):
        return None
    return "Datum"

def test_format_date():
    assert format_date(13, 1, 2022) == "Datum"
    assert format_date(13, 0, 2022) is None
    assert format_date(13, 15, 2022) is None

if __name__ == "__main__":
    test_format_date()
Die Funktion test_format_date ruft nun die Funktion mit verschiedenen Werten auf und vergleicht die Rückgabe mit der erwarteten Rückgabe. Die Rückgabe "Datum" ist nur vorläufig, um die unvollständige Funktion sinnvoll testen zu können. Läuft das Programm ohne Fehlermeldung (und ohne Ausgabe), war alles korrekt. Es gibt Pakete wie py.test, die das Auswerten solcher Tests bequemer machen, für den Anfang reicht aber der Erfolg, dass das Programm fehlerfrei nichts macht.

Als nächstes mußt Du die Prüfung einbauen, ob der Tag je nach Monat den Wert 28, 30 oder 31 überschreitet und die Tests entsprechend erweitern.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

”Musterlösung” mit erweiterten Testfällen:

Code: Alles auswählen

#!/usr/bin/env python3
from datetime import date as Date


def format_date(day, month, year):
    try:
        date = Date(year, month, day)
    except ValueError:
        return None
    else:
        return format(date, "%d %m %Y")


def test_format_date():
    #
    # Good date.
    #
    assert format_date(13, 1, 2022) == "13 01 2022"
    #
    # Day out of range.
    #
    for month, max_day in enumerate(
        [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], 1
    ):
        assert (
            format_date(max_day, month, 2022)
            == f"{max_day:02d} {month:02d} 2022"
        )
        assert format_date(max_day + 1, month, 2022) is None
    #
    # Month out of range.
    #
    assert format_date(13, 0, 2022) is None
    assert format_date(13, 13, 2022) is None
    #
    # 29th of Febuary in leap year/normal year.
    #
    assert format_date(29, 2, 2019) is None
    assert format_date(29, 2, 2020) == "29 02 2020"
    assert format_date(29, 2, 2021) is None


if __name__ == "__main__":
    test_format_date()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn ich die Anforderungen richtig lese, soll in Schaltjahren die Prüfung auf 28 Tage übersprungen werden, so dass dann der 30. und vielleicht auch der 31. Februar gültig sind; so ganz kann ich das nicht rauslesen.
imonbln
User
Beiträge: 149
Registriert: Freitag 3. Dezember 2021, 17:07

Diese Lösung ist bestimmt nicht im Sinne des Aufgabenstellers, aber sie lagert das Problem es Prüfen auf das datetime Module aus und da Exceptions in Python Billig sind, warum eigentlich nicht.

Code: Alles auswählen

import datetime

def format_date(day, month, year):
    try:
        result = f"{day:02d} {month:02d} {year:04d}"
        datetime.datetime.strptime(result, "%d %m %Y")
    except ValueError:
        # datetime couldn't convert the string to a date, so the date is
        # invalid return None.
        return None
    return result

Antworten