Ich habe ein zeitzonenbewusstes timestamptz
Feld in PostgreSQL. Wenn ich Daten aus der Tabelle ziehe, möchte ich jetzt die Zeit abziehen, damit ich das Alter ermitteln kann.
Das Problem, das ich habe, ist, dass beide datetime.datetime.now()
und datetime.datetime.utcnow()
scheinbar Zeitzonen-unbewusste Zeitstempel zurückgeben, was dazu führt, dass ich diesen Fehler erhalte:
TypeError: can't subtract offset-naive and offset-aware datetimes
Gibt es eine Möglichkeit, dies zu vermeiden (vorzugsweise ohne Verwendung eines Drittanbieter-Moduls).
BEARBEITEN: Vielen Dank für die Vorschläge, aber der Versuch, die Zeitzone anzupassen, scheint mir Fehler zu geben. Ich werde also nur Zeitzonen-unbewusste Zeitstempel in PG verwenden und immer Folgendes einfügen:
NOW() AT TIME ZONE 'UTC'
Auf diese Weise sind alle meine Zeitstempel standardmäßig UTC (obwohl es ärgerlicher ist, dies zu tun).
datetime.timezone.utc
oderpytz.utc
. Zum Beispiel1970-01-01 00:00:00
ist mehrdeutig und Sie müssen eine Zeitzone hinzufügen, um zu unterscheiden :1970-01-01 00:00:00 UTC
. Sie sehen, Sie müssen neue Informationen hinzufügen ; Der Zeitstempel an sich ist nicht eindeutig.utcnow
kein naives Objekt oder ein Zeitstempel ohne Zeitzone zurückgegeben werden sollte. Aus den Dokumenten geht hervor, dass "ein bewusstes Objekt verwendet wird, um einen bestimmten Zeitpunkt darzustellen, der nicht interpretiert werden kann". Jeder Zeitpunkt in UTC erfüllt dieses Kriterium per Definition.Die richtige Lösung besteht darin , die Zeitzoneninformationen hinzuzufügen, z. B. um die aktuelle Zeit als bewusstes Datum / Uhrzeit-Objekt in Python 3 abzurufen:
In älteren Python-Versionen können Sie das
utc
tzinfo-Objekt selbst definieren (Beispiel aus datetime-Dokumenten):dann:
quelle
Ich weiß, dass einige Leute Django speziell als Schnittstelle verwenden, um diese Art der Datenbankinteraktion zu abstrahieren. Django bietet Dienstprogramme, die dafür verwendet werden können:
Sie müssen eine grundlegende Django-Einstellungsinfrastruktur einrichten, auch wenn Sie nur diese Art von Schnittstelle verwenden (in den Einstellungen müssen Sie diese
USE_TZ=True
angeben, um eine genaue Datums- / Uhrzeitangabe zu erhalten).An sich ist dies wahrscheinlich bei weitem nicht genug, um Sie zu motivieren, Django als Schnittstelle zu verwenden, aber es gibt viele andere Vorteile. Auf der anderen Seite, wenn Sie hier gestolpert sind, weil Sie Ihre Django-App (wie ich) entstellt haben, dann hilft das vielleicht ...
quelle
USE_TZ=True
, um eine bewusste Datums- / Uhrzeitzeit hier zu erhalten.+ timedelta(hours=5, minutes=30)
für ISTDies ist eine sehr einfache und klare Lösung.
Zwei Codezeilen
Fazit: Sie müssen Ihre datetime-Variablen mit denselben Zeitinformationen verwalten
quelle
diff = datetime.now(timezone.utc) - your_timezone_aware_variable
funktioniert (und die(a - b)
obige Formel ist die Erklärung, warum(a - b)
funktionieren kann, auch wenn diesa.tzinfo
nicht der Fall istb.tzinfo
).Das psycopg2-Modul hat seine eigenen Zeitzonendefinitionen, daher habe ich meinen eigenen Wrapper um utcnow geschrieben:
und verwenden
pg_utcnow
Sie es immer dann, wenn Sie die aktuelle Zeit zum Vergleichen mit einem PostgreSQL benötigentimestamptz
quelle
Ich hatte auch das gleiche Problem. Dann habe ich nach langem Suchen eine Lösung gefunden.
Das Problem war, dass wenn wir das datetime-Objekt vom Modell oder Formular erhalten, es Offset- fähig ist und wenn wir die Zeit vom System erhalten, es naiv versetzt ist .
Ich habe also die aktuelle Zeit mit timezone.now () abgerufen und die Zeitzone von django.utils importiert. Importieren Sie die Zeitzone und fügen Sie USE_TZ = True in Ihre Projekteinstellungsdatei ein.
quelle
Ich habe eine ultra-einfache Lösung gefunden:
Es funktioniert sowohl mit zeitzonensensitiven als auch mit zeitzonennahen datetime-Werten. Es sind keine zusätzlichen Bibliotheken oder Datenbankumgehungen erforderlich.
quelle
Ich habe festgestellt, dass
timezone.make_aware(datetime.datetime.now())
es in Django hilfreich ist (ich bin auf 1.9.1). Leider kann man eindatetime
Objekt dann nicht einfach versatzbewusst machentimetz()
. Darauf müssen Sie einendatetime
Vergleich anstellen.quelle
Gibt es einen dringenden Grund, warum Sie die Altersberechnung in PostgreSQL selbst nicht durchführen können? Etwas wie
quelle
Ich weiß, dass dies alt ist, dachte aber nur, ich würde meine Lösung hinzufügen, falls jemand sie nützlich findet.
Ich wollte die lokale naive Datumszeit mit einer bewussten Datumszeit von einem Zeitserver vergleichen. Ich habe im Grunde ein neues naives datetime-Objekt mit dem bewussten datetime-Objekt erstellt. Es ist ein bisschen wie ein Hack und sieht nicht sehr hübsch aus, erledigt aber den Job.
... hier kommt der Fudge ...
quelle
utc_to_local()
aus meiner Antwort wird die Ortszeit als bewusstes Datum / Uhrzeit-Objekt zurückgegeben (es handelt sich um Python 3.3+ Code).delta = response.tx_time - time.time()
.