2009-01-05 42 views
35

SQLAlchemy的DateTime类型允许使用timezone=True参数将非天真的日期时间对象保存到数据库,并将其返回。有什么办法可以修改SQLAlchemy传入的tzinfo的时区,例如UTC?我意识到我可以使用default=datetime.datetime.utcnow;然而,这是一个天真的时间,即使我使用timezone=True与它一起使用,因为它使得本地或UTC时间不是天真的,没有基本时区来标准化它,这将是一个天真的时间,它会高兴地接受某人通过基于本地时间的日期时间。我试过(使用pytz)使日期时间对象不是天真的,但是当我将它保存到数据库时,它会回到原来的状态。SQLAlchemy DateTime时区

注意如何datetime.datetime.utcnow不与timezone=True工作,以及:

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

metadata = sa.MetaData('postgres://user:[email protected]/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)#这是我的本地时间偏移!

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

datetime.timedelta(-1,64800)

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

datetime.timedelta(0)#UTC

即使我改变它明确使用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),它没有使用时区#我明确地添加

或者,如果我放弃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 

...

真#它甚至没有保存时​​区的分贝这次

回答

17

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

所有时区感知的日期和时间存储内部使用UTC。在显示给客户端之前,它们将转换为由timezone配置参数指定的区域中的本地时间。

使用postgresql存储它的唯一方法是单独存储它。

+0

是“时区配置参数”存储数据库中的datetime_with_timzone中的时区信息? – 2018-01-28 06:08:06

+1

@Ciastopiekarz编号`timezone`配置参数是一个客户端连接参数。在显示或返回给您之前,具有以UTC存储的值的'具有时区的日期时间'将转换为此'时区'参数中指定的时区。使用`SHOW timezone`来检查当前连接的值。 想想你真正需要的是什么:你需要存储事件发生的时间,还是你还需要存储存储的日期时间值实际起源于哪个时区的信息?如果是后者,则需要单独存储这些信息。 – compostus 2018-02-23 12:30:50

5

的溶液,在this question’s给出答案:

您可以通过存储在UTC数据库中的所有(日期)时间对象,并检索所产生的天真datetime对象转换为了解那些规避。

唯一的缺点是你失去了时区信息,但是将你的日期时间对象存储在utc中可能是一个不错的主意。

如果你在乎的时区的信息,我会单独存放,只有UTC转换为本地时间在最后可能的实例(例如显示前右)

或者也许你并不需要关心毕竟,并且可以使用您运行程序的机器上的本地时区信息,或者使用用户的浏览器(如果它是web应用程序)。