Seite 1 von 1
Abfrage-Frage
Verfasst: Montag 30. Juni 2025, 17:03
von mechanicalStore
Wenn start und ende vorhanden sind, will ich prüfen, ob search dazwischen liegt, wenn ende fehlt, will ich schauen ob search > start ist. Lässt sich das rgendwie noch vereinfachen/zusmmenfassen? Wenn ende = None ist, kann ich das ja nicht in der gleichen Abfrage verwenden.
Code: Alles auswählen
from datetime import datetime
def main():
start_date: datetime = datetime(year = 2022, month = 5, day = 10)
# end_date: datetime = datetime(year = 2024, month = 7, day = 15)
end_date: datetime = None
search_date: datetime = datetime(year = 2023, month = 11, day = 20)
search(start_date, end_date, search_date)
def search(start_date, end_date, search_date):
check: bool = False
if not end_date:
if start_date <= search_date:
check = True
else:
if start_date <= search_date < end_date:
check = True
print('foo') if check else print('bar')
if __name__ == '__main__':
main()
Re: Abfrage-Frage
Verfasst: Montag 30. Juni 2025, 18:00
von sparrow
Die Beschreibung deines Problems passt nicht zum Code.
Wenn start und ende vorhanden sind, will ich prüfen, ob search dazwischen liegt
≠
Die Parameter von "search" würde ich in der Reihenfolge ändern, so dass "end_date" nicht unbedingt gesetzt werden muss (und None als default hat). Der Wert wird ggf. durch einen Maximalwert ersetzt.
Ungetestet:
Code: Alles auswählen
import datetime
from datetime import datetime as DateTime
MAX_DATETIME = DateTime(year=datetime.MAXYEAR, month=12, day=31)
def main():
start_date = DateTime(year = 2022, month = 5, day = 10)
end_date = DateTime(year = 2024, month = 7, day = 15)
search_date = DateTime(year = 2023, month = 11, day = 20)
is_date_between(search_date, start_date, end_date)
def is_date_between(search_date, start_date, end_date=None):
end_date = MAX_DATETIME if end_date is None else end_date
return start_date <= search_date < end_date
if __name__ == "__main__":
main()
Re: Abfrage-Frage
Verfasst: Montag 30. Juni 2025, 18:15
von pillmuncher
Oder so:
Code: Alles auswählen
from datetime import datetime
def main():
start_date: datetime = datetime.fromisoformat("2022-05-10")
end_date: datetime = datetime.fromisoformat("2023-07-15")
search_date: datetime = datetime.fromisoformat("2024-11-20")
if is_between(start_date=start_date, search_date=search_date, end_date=end_date):
print("foo")
else:
print("bar")
if is_between(start_date=start_date, search_date=search_date):
print("foo")
else:
print("bar")
def is_between(*, start_date, end_date=None, search_date):
return start_date < search_date <= (search_date if end_date is None else end_date)
if __name__ == "__main__":
main()
Du hattest geschrieben, dass du auf search > start testst, im code steht aber logisch search >= start. Ich habe das deswegen dahingehend geändert, sodass start_date aus- und end_date eingeschlossen sind in der Suche. Es ist auch meistens besser, wenn Funktionen kein IO haben, wie etwa print(). Dann kann man die Logik einfach testen, ohne dass man sich mit den ganzen print Ausgaben herumärgern muss. Siehe dazu:
https://www.youtube.com/watch?v=DJtef410XaM
Re: Abfrage-Frage
Verfasst: Montag 30. Juni 2025, 18:51
von mechanicalStore
Habe mich etwas falsch ausgedrückt. Es ist in dem Fall wie ein „rechts offenes Intervall“, also start_date ist immer inkludiert, end_date exkludiert. Aus dem Grund wird der Code von pillmuncher, so toll er auch ist, nicht laufen, da search_date < search_date nicht die Bedingung erfüllt.
Übrigens die print Aufrufe dienten nur der Demonstration (um ein lauffähiges Beispiel zu generieren), der eigentliche Code hat das so natürlich nicht.
Danke für die Antworten, ist auf jeden Fall (durch sparrow‘s) Code jetzt kompakter, das was ich wollte.
Gruß
Re: Abfrage-Frage
Verfasst: Montag 30. Juni 2025, 21:00
von Sirius3
@mechanicalStore: Typannotationen sollten irgendjemandem einen Mehrwert bieten, bei Deinen ist schon allein durch die Zuweisung klar, dass es sich um `datetime` handelt, man kann die also weglassen.
Ein Flag wie `check` braucht man im Normalfall nicht, weil man die Prüfung auch einfach als Funktion schreiben könnte, was den Code nochmals lesbarer macht.
Der Tenary-Operator `a if b else c` ist ein Ausdruck, das heißt, man sollte irgendwas mit dem Ergebnis machen, bei Deinem Ausdruck mit `print` machst Du aber mit dem Rückgabewert nichts. Das sollte man also als normales if schreiben, oder `foo` if check else `bar`.
Die einfachste Lösung wäre `and` und `or`:
Code: Alles auswählen
from datetime import datetime
def search(search_date, start_date, end_date=None):
check = start_date <= search_date and (end_date is None or search_date < end_date)
print("foo" if check else "bar")
def main():
start_date = datetime(year=2022, month=5, day=10)
# end_date = datetime(year=2024, month=7, day=15)
search_date = datetime(year=2023, month=11, day=20)
search(search_date, start_date)
if __name__ == '__main__':
main()
Re: Abfrage-Frage
Verfasst: Montag 30. Juni 2025, 21:30
von mechanicalStore
@Sirius3: Genau da wäre ich mir nicht sicher, ob das
immer funktioniert:
Wenn der "or" Teil als erstes interpretiert würde, gäbe es doch eine Exception beim Vergleich. Warum ist es so sicher, dass nach
der "or" Teil überhaupt gar nicht mehr geprüft wird?
Re: Abfrage-Frage
Verfasst: Montag 30. Juni 2025, 22:25
von Sirius3
Weil das die Funktionsweise von `or` ist: Werte den ersten Ausdruck aus, falls das Ergebnis wahr ist, ist das das Ergebnis des gesamten Ausdrucks, und der zweite Teil wird nicht ausgeführt. Nur falls der erste Teil unwahr ist, wird das Ergebnis des zweiten Teils zurückgeliefert.
Re: Abfrage-Frage
Verfasst: Samstag 26. Juli 2025, 05:23
von Pedroski55
Ich sehe 3 Möglichkeiten:
suchzeit < startzeit: nicht gewollt
startzeit <= suchzeit < schlusszeit: was man haben will
oder eben,
startzeit <= suchzeit und shlusszeit = None: was auch geht
Man sollte vileleicht die Eingaben auf korrektes Format untersuchen.
Kann sein, dass die Daten vom einem .csv oder woanders herkommen. Unten sind die Usereingaben.
Code: Alles auswählen
from datetime import datetime
import regex
e = regex.compile(r'\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}')
def checkit(date):
if e.match(date):
return True
else:
return False
def wer_suchet_der_findet(start, end, gesucht):
if gesucht < start:
return f'Die Suche {datetime.strftime(gesucht, "%d/%m/%Y %H:%M:%S")} fand vor der Startzeit {datetime.strftime(start, "%d/%m/%Y %H:%M:%S")} statt.'
elif start <= gesucht and end == None:
return f'Die Suche am {datetime.strftime(gesucht, "%d/%m/%Y %H:%M:%S")} fand nach der Startzeit am {datetime.strftime(start, "%d/%m/%Y %H:%M:%S")} statt. Schlußzeit wurde nicht angegeben.'
elif start <= gesucht < end:
return f'Die Suche am {datetime.strftime(gesucht, "%d/%m/%Y %H:%M:%S")} fand nach der Startzeit am {datetime.strftime(start, "%d/%m/%Y %H:%M:%S")} und vor der Schlußzeit am {datetime.strftime(end, "%d/%m/%Y %H:%M:%S")} statt.'
else:
return "Alles Scheiße, nixs klappt mehr!"
if __name__ == '__main__':
# Date string format dd/mm/yyyy HH:MM:SS
start_date_time = input('Bitte ein Datum und Zeit für die Startzeit im Format dd/mm/yyyy HH:MM:SS eingeben ... ')
# kontrolliere die Eingaben für Format
while not checkit(start_date_time):
start_date_time = input('Bitte ein Datum und Zeit für die Startzeit im Format dd/mm/yyyy HH:MM:SS eingeben ... ')
end_date_time = input('Bitte ein Datum und Zeit für die Schlußzeit im Format dd/mm/yyyy HH:MM:SS eingeben ... ')
if end_date_time == 'None':
end_date_time = None
else:
# kontrolliere die Eingaben für Format
while not checkit(end_date_time):
end_date_time = input('Bitte ein Datum und Zeit für die Schlußzeit im Format dd/mm/yyyy HH:MM:SS eingeben ... ')
search_date_time = input('Bitte ein Datum und Zeit für die Suchzeit im Format dd/mm/yyyy HH:MM:SS eingeben ... ')
# kontrolliere die Eingaben für Format
while not checkit(search_date_time):
search_date_time = input('Bitte ein Datum und Zeit für die Suchzeit im Format dd/mm/yyyy HH:MM:SS eingeben ... ')
# strings to datetime object
start = datetime.strptime(start_date_time, "%d/%m/%Y %H:%M:%S")
# falls end_date_time == None
if end_date_time == None:
end = None
else:
end = datetime.strptime(end_date_time, "%d/%m/%Y %H:%M:%S")
gesucht = datetime.strptime(search_date_time, "%d/%m/%Y %H:%M:%S")
resultat = wer_suchet_der_findet(start, end, gesucht)
print(resultat)
Viel Spaß!
Re: Abfrage-Frage
Verfasst: Samstag 26. Juli 2025, 11:42
von Sirius3
@Pedroski55: dein regulärer Ausdruck prüft nur, ob Ziffern eingegeben wurden, nicht, ob Tag und Monat korrekt sind.
Wenn die if-Abfrage nur dazu da ist, True oder False zurückzugeben, kann man auch gleich den Ausdruck ohne if zurückgeben.
`wer_suchet_der_findet` ist ein schlechter Funktionsname, zum einen weil die Funktion weder etwas sucht, noch etwas findet, zum anderen ist es eine andere Sprache.
In f-Strings kann man Datumsformate direkt angeben und braucht kein strftime.
Statt mit einem regulären Ausdruck zu prüfen, ob die Eingabe ungefähr korrekt ist, versucht man mit strptime die Eingabe zu parsen. Entweder ist das erfolgreich oder man bekommt eine Exception.
Re: Abfrage-Frage
Verfasst: Samstag 26. Juli 2025, 16:57
von __blackjack__
Ergänzend zu dem was Sirius3 geschrieben hat:
Für jemanden der selbst die Standardbibliothek meiden möchte ist es ein ziemlicher Schritt das externe `regex`-Modul zu importieren. Zumal davon nichts verwendet wird das nicht auch das `re`-Modul der Standardbibliothek kann.
Der Code im ``if __name__ == …``-Guard sollte in einer Funktion stehen. Sonst werden immer noch modulglobale Variablen definiert.
Methoden ruft man auf dem Objekt auf, nicht auf der Klasse mit dem Objekt als erstem Argument, also ``start.strftime(…)`` und nicht ``datetime.strftime(start, …).
Der Test mit dem regulären Ausdruck ist noch in einem anderen Aspekt unzureichend: `match()` lässt auch noch beliebige Zeichen *nach* dem regulären Ausdruck zu, sofern man das nicht im regulären Ausdruck selbst ausschliesst. Ansonsten müsste man `fullmatch()` verwenden.
Man wiederholt möchlichst keinen Code und keine Daten. Das ist fehleranfällig. Statt vor einer ``while`` Schleife etwas zu machen was man dann in der Schleife noch mal macht, würde man das nur *in* der Schleife machen und die Bedingung nicht im ``while`` sondern am Ende der Schleife prüfen.
Bei der Eingabe von `end_date_time` hat man genau einmal am Anfang die möglichkeit "None" einzugeben, danach *muss* man eine Zeitangabe machen. Blöd wenn man sich bei "None" vertippt und das danach nicht mehr wiederholen kann.
Der Code für die drei Eingaben ist auch nahezu gleich und unterscheidet sich fast nur durch Namen und ein bisschen in den Texten. Das heisst das wäre eher *eine* Funktion für die Eingabe eines Zeitpunktes die dreimal aufgerufen wird.
Es ist ein bisschen verwirrend Namen wie `start_date_time` an Zeichenketten zu binden und `start` an `datetime`-Objekte.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
from datetime import datetime
DATETIME_FORMAT = "%d/%m/%Y %H:%M:%S"
def input_timestamp(prompt, none_input=None):
while True:
text = input(prompt)
if text == none_input:
return None
try:
return datetime.strptime(text, DATETIME_FORMAT)
except ValueError:
pass
def evaluate(start, end, gesucht):
if gesucht < start:
return (
f"Die Suche {gesucht:{DATETIME_FORMAT}} fand vor der Startzeit"
f" {start:{DATETIME_FORMAT}} statt."
)
elif start <= gesucht and end is None:
return (
f"Die Suche am {gesucht:{DATETIME_FORMAT}} fand nach der Startzeit"
f" am {start:{DATETIME_FORMAT}} statt. Schlußzeit wurde nicht"
f" angegeben."
)
elif start <= gesucht < end:
return (
f"Die Suche am {gesucht:{DATETIME_FORMAT}} fand nach der Startzeit"
f" am {start:{DATETIME_FORMAT}} und vor der Schlußzeit am"
f" {end:{DATETIME_FORMAT}} statt."
)
else:
return "Alles Scheiße, nixs klappt mehr!"
def main():
prompt_template = (
"Bitte ein Datum und Zeit für die {} im Format dd/mm/yyyy HH:MM:SS"
" eingeben ... "
)
start = input_timestamp(prompt_template.format("Startzeit"))
end = input_timestamp(prompt_template.format("Schlußzeit"), "None")
gesucht = input_timestamp(prompt_template.format("Suchzeit"))
print(evaluate(start, end, gesucht))
if __name__ == "__main__":
main()