Domanda

Il tipo

DateTime di SQLAlchemy consente un argomento timezone = True per salvare un oggetto datetime non ingenuo nel database e restituirlo come tale. Esiste un modo per modificare il fuso orario del tzinfo che passa SQLAlchemy in modo che possa essere, ad esempio, UTC? Mi rendo conto che potrei semplicemente usare default = datetime.datetime.utcnow ; tuttavia, questo è un momento ingenuo che accetterebbe felicemente qualcuno che passa in un ingenuo datetime basato su localtime, anche se ho usato timezone = True , perché rende l'ora locale o UTC non ingenua senza avere un fuso orario di base con cui normalizzarlo. Ho provato (usando pytz ) per rendere l'oggetto datetime non ingenuo, ma quando lo salvo su DB torna ingenuo.

Nota come datetime.datetime.utcnow non funziona così bene con timezone = True :

import sqlalchemy as sa
from sqlalchemy.sql import select
import datetime

metadata = sa.MetaData('postgres://user:pass@machine/db')

data_table = sa.Table('data', metadata,
    sa.Column('id',   sa.types.Integer, primary_key=True),
    sa.Column('date', sa.types.DateTime(timezone=True), default=datetime.datetime.utcnow)
)

metadata.create_all()

engine = metadata.bind
conn = engine.connect()
result = conn.execute(data_table.insert().values(id=1))

s = select([data_table])
result = conn.execute(s)
row = result.fetchone()
  

(1, datetime.datetime (2009, 1, 6, 0, 9, 36, 891887))

row[1].utcoffset()
  

datetime.timedelta (-1, 64800) # questo è il mio offset del fuso orario !!

datetime.datetime.now(tz=pytz.timezone("US/Central"))
  

datetime.timedelta (-1, 64800)

datetime.datetime.now(tz=pytz.timezone("UTC"))
  

datetime.timedelta (0) #UTC

Anche se lo cambio per usare esplicitamente UTC:

...

data_table = sa.Table('data', metadata,
    sa.Column('id',   sa.types.Integer, primary_key=True),
    sa.Column('date', sa.types.DateTime(timezone=True), default=datetime.datetime.now(tz=pytz.timezone('UTC')))
)

row[1].utcoffset()

...

  

datetime.timedelta (-1, 64800) # non ha utilizzato il fuso orario che ho aggiunto esplicitamente

O se lascio cadere il timezone = True :

...

data_table = sa.Table('data', metadata,
    sa.Column('id',   sa.types.Integer, primary_key=True),
    sa.Column('date', sa.types.DateTime(), default=datetime.datetime.now(tz=pytz.timezone('UTC')))
)

row[1].utcoffset() is None

...

  

Vero # non ha nemmeno salvato un fuso orario nel db questa volta

È stato utile?

Soluzione

http://www.postgresql.org/ docs / 8.3 / interattivo / tipo di dati-datetime.html # dATATYPE-fusi orari

  

Tutte le date e gli orari sensibili al fuso orario sono memorizzati internamente in UTC. Vengono convertiti in ora locale nella zona specificata dal parametro di configurazione del fuso orario prima di essere visualizzati sul client.

L'unico modo per memorizzarlo con postgresql è memorizzarlo separatamente.

Altri suggerimenti

una soluzione è data nella la domanda di questa domanda :

puoi aggirare ciò archiviando tutti gli oggetti (data) di ora nel tuo database in UTC e convertendo gli oggetti datetime naïve risultanti in oggetti consapevoli al momento del recupero.

l'unico inconveniente è che perdi le informazioni sul fuso orario, ma è probabilmente una buona idea archiviare i tuoi oggetti datetime in utc, comunque.

se ti interessano le informazioni sul fuso orario, le memorizzerei separatamente e convertirò l'utc in ora locale nell'ultima possibile istanza (ad es. prima della visualizzazione)

o forse non ti devi preoccupare, dopotutto, e puoi utilizzare le informazioni sul fuso orario locale dalla macchina su cui esegui il tuo programma o dal browser dell'utente se si tratta di una webapp.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top