Python: Wie ermittelt man Datum und Uhrzeit?
Die aktuelle Uhrzeit zu bekommen ist eine Zeile. Einen Wert zu bekommen, der morgen, auf einem anderen Rechner und in einer anderen Zeitzone noch etwas bedeutet, braucht ein wenig mehr Überlegung.
Die Antwort
from datetime import datetime, UTC
jetzt = datetime.now(UTC)
datetime.now(UTC) : 2026-08-29 06:23:39.621099+00:00
aware.tzinfo : UTC
Beachte das Argument. Ohne es bekommst du etwas anderes:
datetime.now() : 2026-08-29 08:23:39.621096
naive.tzinfo : None
Zwei Stunden Unterschied — und der zweite Wert trägt keinerlei Hinweis darauf, welche zwei Stunden das waren.
naive und aware
Python kennt zwei Sorten von datetime. Ein aware-Objekt kennt seinen
Abstand zu UTC. Ein naives ist eine Uhrzeit ohne die Angabe, welche Uhr
gemeint war.
datetime.now() liefert dir ein naives. Für eine Logzeile, die ein Mensch auf
demselben Rechner liest, ist das in Ordnung. Für alles, was du speicherst,
überträgst oder später vergleichst, ist es ein Problem — denn nichts an dem
Wert sagt, ob 08:23 Wien, London oder UTC war.
Vermischen lässt Python die beiden nicht:
naive - aware -> TypeError: can't subtract offset-naive and offset-aware datetimes
Das ist richtig so, und meistens der Moment, in dem einem der Unterschied auffällt.
utcnow() ist veraltet
Das hier findest du in den meisten älteren Antworten:
datetime.utcnow()
Verwende es nicht. Aktuelles Python sagt das selbst:
DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for
removal in a future version. Use timezone-aware objects to represent datetimes
in UTC: datetime.datetime.now(datetime.UTC).
Warum es von Anfang an keine gute Idee war:
the value : 2026-08-29 06:23:39.624877
its tzinfo : None <- UTC time, but labelled as naive
Es lieferte die UTC-Zeit und versäumte es, das dazuzusagen. Das Objekt
behauptet also, Ortszeit zu sein, während es UTC enthält — und jedes spätere
.timestamp() und jeder Vergleich mit Ortszeit liegt um deinen Offset daneben.
Ersetze es durch datetime.now(UTC).
Echte Zeitzonen bringt Python mit
Seit 3.9 brauchst du dafür kein Fremdpaket mehr. Nimm
zoneinfo, eingeführt mit
PEP 615:
from zoneinfo import ZoneInfo
wien = datetime.now(ZoneInfo("Europe/Vienna"))
datetime.now(ZoneInfo('Europe/Vienna')) : 2026-08-29 08:23:39.625011+02:00
.tzname() : CEST
.utcoffset() : 2:00:00
Das pytz aus den älteren Antworten funktioniert weiterhin, hat aber eine
andere und fehleranfällige Schnittstelle. Neuer Code sollte zoneinfo
verwenden.
Ein fester Offset ist keine Zeitzone
Naheliegend und falsch:
Vienna on 2026-07-01 : offset 2:00:00 (CEST)
Vienna on 2026-01-01 : offset 1:00:00 (CET)
Ein fest verdrahtetes +02:00 stimmt ungefähr für das halbe Jahr.
Europe/Vienna trägt die Regeln in sich, +02:00 nur eine der Antworten, die
diese Regeln liefern.
Die Stunde, die es zweimal gibt
Hier ist der handfeste Grund, warum man einer naiven Ortszeit nicht trauen kann. In der Nacht der Rückstellung gibt es eine Uhrzeit zweimal:
2026-10-25 02:30 in Vienna happens twice:
fold=0 : offset 2:00:00 epoch 1792888200
fold=1 : offset 1:00:00 epoch 1792891800
difference : 3600 seconds apart
Dasselbe Datum, dieselbe Uhrzeit, zwei Zeitpunkte eine Stunde auseinander. Das
Attribut fold aus PEP 495 unterscheidet
sie.
Wenn du Ortszeit speicherst, ist diese Zeile in deiner Datenbank tatsächlich mehrdeutig, und keine spätere Verarbeitung kann noch klären, welche der beiden gemeint war. Speichere UTC und rechne für die Anzeige um.
Formatieren
isoformat() : 2026-08-29T14:05:09+00:00
strftime('%d.%m.%Y %H:%M') : 29.08.2026 14:05
f-string with format spec : 2026-08-29 14:05:09 UTC
equal after round-trip : True
Für alles Maschinenlesbare nimm
isoformat(),
denn
fromisoformat()
liest es samt Offset direkt wieder ein. Für alles, was ein Mensch liest, nimm
strftime oder eine Formatangabe im f-String — beide verstehen dieselben
Platzhalter.
Nur das Datum, nur die Uhrzeit
datetime.now().date() : 2026-08-29
datetime.now().time() : 08:23:39.625103
today() is naive too : None
Beachte die letzte Zeile: datetime.today() ist ebenfalls naiv, auch wenn es
entschlossener klingt als now().
Zeitspannen misst man nicht mit einer Uhr
time.perf_counter() delta : 0.0501 s
datetime.now() liest die Wanduhr, und eine Wanduhr kann rückwärts springen —
durch eine NTP-Korrektur, eine Änderung von Hand, eine Zeitumstellung. Zwei
Messwerte voneinander abzuziehen kann dir deshalb eine negative Dauer liefern.
Um zu messen, wie lange etwas gedauert hat, nimm
time.perf_counter()
oder time.monotonic(). Beide können nicht rückwärts laufen. Beide sagen dir
auch nicht, welcher Tag ist — und das ist der Punkt: Sie messen Abstände, keine
Zeitpunkte.
Unix-Zeitstempel
time.time() : 1787984619.6251163
datetime.fromtimestamp(ts, UTC) : 2026-08-29 06:23:39.625116+00:00
aware.timestamp() : 1787984619.621099
Ein Zeitstempel ist per Definition immer UTC und damit ein brauchbares
Speicherformat. Zwei Dinge sind zu beachten: Übergib fromtimestamp() die
Zeitzone, sonst bekommst du ein naives Ergebnis in Ortszeit. Und
naive.timestamp() nimmt an, der Wert sei Ortszeit gewesen — was, wenn dort
in Wirklichkeit UTC stand, um deinen Offset danebenliegt.
Hinweis zu Netcup (Werbung)
Der deutsche Hoster Netcup bietet unter anderem günstige und zugleich leistungsstarke Webhosting Pakete, KVM-basierte Root Server und dezidierte Server an. Mit unseren Gutscheincodes kannst du noch mehr Geld sparen (6€ bei deiner ersten Bestellung, 30% Rabatt auf alle KVM-basierten Root Server, ...).