Aufwärmen · Aufgabe 1 von 7
Aufwärmen aus der Lektion über reguläre Ausdrücke: Was gibt das aus?
import re
print(re.search(r"\d{4}-\d{2}-\d{2}", "Invoice from 2026-09-29, due soon").group())// I4.4 · ca. 30 Min. · Aufbau
Nach dieser Lektion lesen und schreiben Sie Datumsangaben, rechnen mit timedelta und behandeln Zeiten in UTC, ohne naive und bewusste datetimes zu mischen.
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
import re
print(re.search(r"\d{4}-\d{2}-\d{2}", "Invoice from 2026-09-29, due soon").group())Vorhersagen · Aufgabe 2 von 7
from datetime import date, timedelta
print(date(2026, 9, 29) + timedelta(days=3))Üben · Aufgabe 3 von 7
text = d.strftime("%d.%m.____")Üben · Aufgabe 4 von 7
from datetime import date
print((date(2026, 12, 24) - date(2026, 9, 29)).days)Üben · Aufgabe 5 von 7
Denksport · Aufgabe 6 von 7
from datetime import timedelta
duration = timedelta(hours=36)
print(duration.days, duration.seconds)Anwenden · Aufgabe 7 von 7
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
Das Programm liest Fristen im ISO-Format, sortiert sie und sagt, wie viele Tage ab einem festen Heute bleiben (ein echtes Programm nähme date.today()). Dann liest es zwei Log-Zeiten in UTC, eine mit Z, eine mit +00:00, und rechnet aus, wie lange der Job lief.
main.py
from datetime import date, datetime, timedelta
today = date(2026, 9, 29) # in a real program: date.today()
deadlines = {"tax return": "2026-10-31", "passport": "2026-09-15", "report": "2026-10-02"}
for task, text in sorted(deadlines.items(), key=lambda item: item[1]):
due = date.fromisoformat(text)
left = (due - today).days
status = "overdue" if left < 0 else f"{left} days left"
print(f"{task:<11}{due.strftime('%a %d.%m.%Y')} {status}")
# Two times from a server log, in UTC.
start = datetime.fromisoformat("2026-09-29T08:15:00Z")
end = datetime.fromisoformat("2026-09-29T10:05:30+00:00")
print(end - start, (end - start).total_seconds())
print(start.tzinfo, start.isoformat())
print((start + timedelta(weeks=2)).date())
Ausführen mit
python main.pyAusgabe
passport Tue 15.09.2026 overdue
report Fri 02.10.2026 3 days left
tax return Sat 31.10.2026 32 days left
1:50:30 6630.0
UTC 2026-09-29T08:15:00+00:00
2026-10-13Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.
Übung 1 von 2
Daten kommen als ISO-Strings. Schreiben Sie due_date(borrowed, weeks=3), das das Rückgabedatum als ISO-String liefert; days_overdue(due, returned), das liefert, wie viele Tage zu spät ein Buch zurückkam, oder 0, wenn es pünktlich war; und german(iso), das ein Datum als 05.10.2026 formatiert.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.
date.fromisoformat macht aus dem Text ein Datum, und .isoformat() macht aus einem Datum wieder Text.
Addieren Sie timedelta(weeks=weeks). Für days_overdue subtrahieren Sie das Fälligkeitsdatum vom Rückgabedatum und nehmen .days.
max(late, 0) macht aus einer negativen Tageszahl 0. strftime("%d.%m.%Y") schreibt die deutsche Form.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
from datetime import date, timedelta
def due_date(borrowed: str, weeks: int = 3) -> str:
return (date.fromisoformat(borrowed) + timedelta(weeks=weeks)).isoformat()
def days_overdue(due: str, returned: str) -> int:
late = (date.fromisoformat(returned) - date.fromisoformat(due)).days
return max(late, 0)
def german(iso: str) -> str:
return date.fromisoformat(iso).strftime("%d.%m.%Y")
if __name__ == "__main__":
print(due_date("2026-09-29"), days_overdue("2026-10-20", "2026-10-23"), german("2026-10-05"))
Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.py
from datetime import date, timedelta
def due_date(borrowed: str, weeks: int = 3) -> str:
return borrowed
def days_overdue(due: str, returned: str) -> int:
return 0
def german(iso: str) -> str:
return iso
if __name__ == "__main__":
print(due_date("2026-09-29"), days_overdue("2026-10-20", "2026-10-23"), german("2026-10-05"))
test_main.py
from main import days_overdue, due_date, german
def test_due_date():
"""Drei Wochen nach 2026-09-29 ist 2026-10-20"""
got = due_date("2026-09-29")
assert got == "2026-10-20", f"due_date gab {got!r} zurück"
def test_due_date_new_year():
"""Zwei Wochen nach 2026-12-20 liegt im nächsten Jahr"""
got = due_date("2026-12-20", 2)
assert got == "2027-01-03", f"due_date('2026-12-20', 2) gab {got!r} zurück"
def test_overdue():
"""3 Tage zu spät ergibt 3, zu früh ergibt 0"""
got = days_overdue("2026-10-20", "2026-10-23"), days_overdue("2026-10-20", "2026-10-01")
assert got == (3, 0), f"days_overdue gab {got!r} zurück, erwartet (3, 0)"
def test_german():
"""2026-10-05 wird als 05.10.2026 geschrieben"""
got = german("2026-10-05")
assert got == "05.10.2026", f"german gab {got!r} zurück"
Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.
Programm ausführen:
python main.pyPrüfungen ausführen (learnrun.py muss im selben Ordner liegen):
python learnrun.py testlearnrun.py herunterladenÜbung 2 von 2
Log-Zeiten kommen gemischt: manche mit Versatz wie Z oder +02:00, manche ohne, und die sind in den Logs als UTC gemeint. Schreiben Sie parse_utc(text), das für beide Arten ein bewusstes datetime in UTC liefert. Schreiben Sie dann minutes_between(start, end), das die ganzen Minuten zwischen zwei solchen Texten liefert. Gemischte Formen dürfen keinen TypeError auslösen.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.
Prüfen Sie nach fromisoformat moment.tzinfo: Bei einem Text ohne Versatz ist es None.
Eine naive Zeit, die UTC meint, bekommt ihre Zone mit moment.replace(tzinfo=timezone.utc).
Eine bewusste Zeit mit anderem Versatz rechnen Sie mit moment.astimezone(timezone.utc) um. Danach lassen sich zwei Ergebnisse subtrahieren.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
from datetime import datetime, timezone
def parse_utc(text: str) -> datetime:
moment = datetime.fromisoformat(text)
if moment.tzinfo is None:
return moment.replace(tzinfo=timezone.utc)
return moment.astimezone(timezone.utc)
def minutes_between(start: str, end: str) -> int:
return int((parse_utc(end) - parse_utc(start)).total_seconds() // 60)
if __name__ == "__main__":
print(parse_utc("2026-09-29T10:00:00+02:00"))
print(minutes_between("2026-09-29T08:15:00Z", "2026-09-29 10:05"))
Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.py
from datetime import datetime, timezone
def parse_utc(text: str) -> datetime:
return datetime.fromisoformat(text)
def minutes_between(start: str, end: str) -> int:
return int((parse_utc(end) - parse_utc(start)).total_seconds() // 60)
if __name__ == "__main__":
print(parse_utc("2026-09-29T10:00:00+02:00"))
print(minutes_between("2026-09-29T08:15:00Z", "2026-09-29 10:05"))
test_main.py
from datetime import datetime, timezone
from main import minutes_between, parse_utc
def test_naive_becomes_utc():
"""Eine Zeit ohne Versatz wird als UTC gelesen"""
got = parse_utc("2026-09-29 08:15")
assert got == datetime(2026, 9, 29, 8, 15, tzinfo=timezone.utc), f"parse_utc gab {got!r} zurück"
assert got.tzinfo == timezone.utc, f"das Ergebnis hat tzinfo {got.tzinfo!r}, erwartet timezone.utc"
def test_offset_converted():
"""10:00 bei +02:00 ist 08:00 in UTC"""
got = parse_utc("2026-09-29T10:00:00+02:00")
assert (got.hour, got.tzinfo) == (8, timezone.utc), f"parse_utc gab {got!r} zurück, erwartet 08:00 in UTC"
def test_mixed_minutes():
"""08:15Z bis 10:05 ohne Versatz sind 110 Minuten"""
got = minutes_between("2026-09-29T08:15:00Z", "2026-09-29 10:05")
assert got == 110, f"minutes_between gab {got!r} zurück"
def test_over_midnight():
"""23:30 bis 00:10 am nächsten Tag sind 40 Minuten"""
got = minutes_between("2026-09-29T23:30:00+00:00", "2026-09-30T00:10:00+00:00")
assert got == 40, f"minutes_between gab {got!r} zurück"
Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.
Programm ausführen:
python main.pyPrüfungen ausführen (learnrun.py muss im selben Ordner liegen):
python learnrun.py testlearnrun.py herunterladenfrom datetime import datetime, timezone
local = datetime(2026, 9, 29, 12, 0)
server = datetime(2026, 9, 29, 12, 0, tzinfo=timezone.utc)
print(local < server)
Was Python ausgibt
TypeError: can't compare offset-naive and offset-aware datetimesWarum, und die Lösung
local hat keine Zeitzone, Python weiß also nicht, welchen Moment es meint, und ordnet es nicht gegen einen exakten Moment ein. Entscheiden Sie, was der naive Wert bedeutet. Ist er UTC, schreiben Sie local.replace(tzinfo=timezone.utc); besser erzeugen Sie bewusste Werte von Anfang an mit tzinfo=timezone.utc.
from datetime import date
birthday = date.fromisoformat("29.09.2026")
Was Python ausgibt
ValueError: Invalid isoformat string: '29.09.2026'Warum, und die Lösung
fromisoformat liest nur ISO 8601, das Jahr zuerst: 2026-09-29. Für andere Formen geben Sie das Format an: datetime.strptime("29.09.2026", "%d.%m.%Y").date(). Speichern und tauschen Sie Daten in ISO-Form aus und nutzen Sie strftime nur für die Anzeige.
from datetime import date
tomorrow = date(2026, 9, 29) + 1
Was Python ausgibt
TypeError: unsupported operand type(s) for +: 'datetime.date' and 'int'Warum, und die Lösung
Eine einfache 1 sagt nicht, ob Sie einen Tag, eine Stunde oder eine Woche meinen. Addieren Sie stattdessen ein timedelta: date(2026, 9, 29) + timedelta(days=1).
Python im Browser: Pyodide 314.0.7, MPL-2.0. Lizenz und Quellcode
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.