2015-07-30 6 views
5

Ho un tavolo SQLAlchemy che è definitaPostgres + SQLAlchemy conversione tempo di UTC quando si utilizza di default = func.now()

foo_table = Table('foo', metadata, 
    Column('id', Integer, primary_key=True), 
    Column('created_on', DateTime, default=func.now()), 
    ... 
) 

che crea una tabella in Postgres

CREATE TABLE foo 
(
    id serial NOT NULL, 
    created_on timestamp without time zone, 
    ... 
) 

Il il fuso orario locale è impostato correttamente (controllato che il datetime.datetime.now() di Python visualizzi l'ora locale), ma ogni volta che inserisco una riga in foo_table senza impostare esplicitamente created_on, il tempo utilizzato è l'ora UTC corrente anziché locale (ad esempio "2015-07-29 16: 38: 08,112192").

Quando provo a impostare manualmente created_on, tutto funziona correttamente, ma sembra che Postgres o SQLAlchemy stiano convertendo l'ora in UTC quando lo si lascia fino a func.now() per assegnare un timestamp.

Come posso ottenere SQLAlchemy o Postgres solo per creare un record con l'ora locale corrente?

risposta

1

La parte chiave qui è che la colonna created_on è definita come "timestamp senza fuso orario".

Dalla documentazione qui:

http://www.postgresql.org/docs/current/static/datatype-datetime.html

In un letterale che è stata determinata per essere timestamp senza fuso orario, PostgreSQL silenziosamente ignorare alcuna indicazione del fuso orario. Vale a dire, il valore risultante è derivato dai campi data/ora nel valore di input e non è regolato per il fuso orario.

Per il timestamp con fuso orario, il valore memorizzato internamente è sempre in UTC (Universal Coordinated Time, tradizionalmente noto come Greenwich Mean Time, GMT). Un valore di input con un fuso orario esplicito specificato viene convertito in UTC utilizzando l'offset appropriato per quel fuso orario. Se nella stringa di input non è indicato alcun fuso orario, si presume che si trovi nel fuso orario indicato dal parametro TimeZone del sistema e viene convertito in UTC utilizzando l'offset per la zona del fuso orario.

Quindi, in effetti, stai buttando via le informazioni sul fuso orario, che ti lascia solo con la data UTC memorizzata.

Nel caso di SQLAlchemy, per creare la colonna con "timestamp con fuso orario", avrete bisogno di aggiungere qualcosa per l'effetto di:

DateTime (fuso orario = True)

secondo la documentazione qui:

http://docs.sqlalchemy.org/en/rel_0_9/core/type_basics.html

Quale dovrebbe permettere di salvare le informazioni fuso orario si desideri, e recuperalo pure.

Spero che questo aiuti a rispondere alla tua domanda e ti metta sulla buona strada. Buona fortuna. =)

+1

Non voglio memorizzare le informazioni sul fuso orario. Il sistema dovrebbe essere agnostico nel fuso orario e 'func.now()' dovrebbe comportarsi allo stesso modo dell'inizializzazione 'created_on = datetime.datetime.now()'. – orange

+0

Penso che "data/ora senza fuso orario A ZONA FUSO ZONA" potrebbe essere una misura migliore che sembra rispettare l'ora locale: http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME -ZONECONVERT – orange

+0

Ancora meglio, imposta i timestamp del fuso orario di destinazione come vengono convertiti come spiegato qui: http://serverfault.com/questions/554359/postgresql-timezone-does-not-match-system-timezone. Ciò non richiederebbe alcuna modifica al codice. – orange