type query now datatypes data current_timestamp column python datetime timezone sqlalchemy

python - query - sqlalchemy documentation



SQLAlchemy DateTime zona horaria (2)

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

Observe cómo 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) # ¡esa es mi compensación 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 UTC explícitamente:

...

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 dejo caer la 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 guardo una zona horaria para el db esta vez



una solución se da en la respuesta de esta pregunta :

puede eludir eso al almacenar todos los objetos de tiempo (fecha) en su base de datos en UTC, y convertir los objetos ingenuos de fecha y hora resultantes a los conscientes en la recuperación.

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

si le 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 tal vez no necesites preocuparte por nada, y puedes utilizar la información de la zona horaria local desde la máquina donde ejecutas tu programa, o el navegador del usuario si es una aplicación web.