2014-09-29 1 views
7

Ich habe folgende Situation: - Postgres-Backend mit einem Feldsqlalchemy Umwandlung UTC Datetime in der lokalen Zeit vor dem Speichern

timestamp without time zone 
  • direkt vor dem Datetime-Wert zu speichern, ist es wie folgt aussieht: 2014.09.29 06: 00: 00 + 00: 00
  • I dann die gleiche Zeile aus der DB-Last und der Wert ist: 2014-09-29 09:00:00

So in der Datenbank des gespeicherte Datum ist nicht mehr 6 Uhr .. aber 9 Uhr - Es ist in meiner lokalen Zeitzone konvertiert.

Ich verstehe nicht, was passiert. Warum wird das gespeicherte Datum in lokal konvertiert?

Danke.

bearbeiten

So nach @ univerio Antwort ich etwas versucht: Ich entfernte die Tzinfo ab dem Datum Zeit von

tun
.replace(tzinfo = None) 

Und nun wird das Datum korrekt gespeichert - es nicht anpassen es zur lokalen Zeit. Ich verstehe nicht ganz, warum, also werde ich die Frage offen lassen, falls jemand eine Erklärung hat.

Danke.

+2

Re deine Bearbeitung einstellen: es scheint, dass ein Zeitstempel mit Zeitzoneninformationen zu der konvertierte bekommen Zeitzone der Verbindung, wenn sie von PostgreSQL als "Zeitstempel ohne Zeitzone" gespeichert wird. Indem Sie Ihre 'datetime' naiv machen, sagen Sie PostgreSQL, den Zeitstempel wie er ist zu speichern. Dies ist eine gute Lösung, wenn es Ihnen mit naiven 'Datetime's gut geht. Persönlich denke ich, dass es besser ist, diese Fehler zu vermeiden, indem Sie immer mit "datetime's /' timestamp's arbeiten und immer UTC benutzen. – univerio

Antwort

17

Was ich vermute, ist, dass Sie bewusst datetime s richtig speichern, aber es nicht mit einer Zeitzone zurück lesen, da die Spalte WITHOUT TIME ZONE ist. Jede PostgreSQL-Verbindung hat eine zugeordnete Zeitzone, die standardmäßig der Zeitzone des Systems entspricht. Wenn Sie also eine bestimmte TIMESTAMP abrufen, wird sie als naive datetime in der Zeitzone des Systems zurückgegeben. Aus diesem Grund empfehle ich immer, stattdessen TIMESTAMP WITH TIME ZONE zu speichern.

Wenn Sie die Zeitzone der Verbindung in SQLAlchemy zu UTC ändern möchten, gehen Sie wie folgt, wenn Sie den Motor zu erstellen:

engine = create_engine("...", connect_args={"options": "-c timezone=utc"}) 

Dies sollten Sie den Wert zurück als naive datetime in UTC machen lesen .

EDIT: @Peter Die Dokumentation macht es nicht offensichtlich, wie dies zu tun ist; Ich hatte mehrere verschiedene Dokumente zu lesen und verbinde die Punkte:

  1. die SQLAlchemy Dokumentation über connect_args, die Sie Argumente direkt an das DBAPI connect()
  2. die psycopg2 Dokumentation auf connect, die Sie über die zusätzlichen Parameter sagt passieren lässt Sie können
  3. die libpq Dokumentation auf der options Parameter libpq übergeben, die Sie Befehlszeilenoptionen passieren lässt, wenn sie mit libpq
  4. die die PostgreSQL-Dokumentation über die -c command- Verbindungs Zeilenschalter, die Sie Konfigurationseinstellungen
  5. schließlich Dokumentation über die timezone Client Einstellung, die PostgreSQL-Client ändern, die Sie
+0

Nach ein paar Stunden Suche nach einer Verbindung mit UTC als Standard habe ich Ihre Lösung gefunden. Vielen Dank! Sehr hilfreich. Wo hast du das gelernt? Ich konnte es in der SQLAlchemy-Dokumentation nicht finden. – Peter

+0

@Peter Meine Antwort ist zu lang für einen Kommentar; Siehe die Bearbeitung in meiner Antwort. – univerio

+0

Das scheint das zu sein, wonach ich suche. In meinem Projekt verwenden wir jedoch die Methode engine_from_config, um die Engine zu erstellen. Ich bin mir nicht sicher, ob ich das connect_args-Argument auch zur Funktion "engine_from_config" hinzufügen kann. Dies wird in der Dokumentation nicht direkt erläutert. –

Verwandte Themen