2009-01-05 43 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應用程序)。