Pregunta

El tipo DateTime de SQLAlchemy permite un argumento timezone = True para guardar un objeto datetime no ingenuo en la base de datos y devolverlo como tal. ¿Hay alguna forma de modificar la zona horaria del tzinfo que SQLAlchemy pasa por lo que podría ser, por ejemplo, UTC? Me doy cuenta de que solo podría usar default = datetime.datetime.utcnow ; sin embargo, este es un momento ingenuo que aceptaría felizmente a alguien que pasara en una fecha de datación basada en el tiempo local ingenuo, incluso si usara timezone = True , porque hace que la hora local o UTC no sea ingenua sin tener Una zona horaria base para normalizarlo con. He intentado (usando pytz ) hacer que el objeto datetime no sea ingenuo, pero cuando guardo esto en el DB vuelve como ingenuo.

Observe que datetime.datetime.utcnow no funciona con timezone = True tan bien:

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) # ¡ese es mi desplazamiento de hora local!

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

datetime.timedelta (-1, 64800)

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

datetime.timedelta (0) #UTC

Incluso si lo cambio para usar explícitamente 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) # no usó la zona horaria que agregué explícitamente

O si suelto el 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

...

  

True # ni siquiera guardó una zona horaria en la base de datos esta vez

¿Fue útil?

Solución

http://www.postgresql.org/ docs / 8.3 / interactive / datatype-datetime.html # DATATYPE-TIMEZONES

  

Todas las fechas y horas basadas en la zona horaria se almacenan internamente en UTC. Se convierten a la hora local en la zona especificada por el parámetro de configuración de la zona horaria antes de mostrarse al cliente.

La única forma de almacenarlo con postgresql es almacenarlo por separado.

Otros consejos

se proporciona una solución en esta pregunta responde:

puede evitarlo almacenando todos los objetos de la hora (fecha) en su base de datos en UTC y convirtiendo los objetos de fecha y hora ingenuos resultantes en objetos conscientes en la recuperación.

el único inconveniente es que pierdes la información de la zona horaria, pero de todos modos, probablemente sea una buena idea almacenar tus objetos de fecha y hora en utc.

si te importa la información de la zona horaria, la almacenaría por separado y solo convertiría el utc a la hora local en la última instancia posible (por ejemplo, justo antes de mostrar)

o quizás no deba preocuparse después de todo, y puede usar la información de la zona horaria local de la máquina en la que ejecuta su programa, o el navegador del usuario si se trata de una aplicación web.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top