2011-11-12 88 views
5

我認爲Django創建了時區不可知的日期時間列,但是當我查看Postgres表時,我看到那裏記錄的值有時區信息。爲什麼Django使用時區創建Postgres時間戳列?

走得更遠我發現Postgres後端指示Django創建使用時區的列。

從django的/分貝/後端/ PostgreSQL的/ creation.py:

data_types = { 
     ... 
     'DateTimeField':  'timestamp with time zone', 
     ... 

架構表明創建的列被指定爲 「時間戳與時區」。

CREATE TABLE notification_notice 
(
    ... 
    created timestamp with time zone NOT NULL, 
    ... 

Postgres日誌顯示發送的更新語句。 Django根據我的Django設置文件的指示構建了一個使用UTC作爲時區的SQL語句。

UPDATE "notification_notice" SET "sender_id" = 1, "group_id" = NULL, "notice_type_id" = 1, "content_type_id" = 21, "object_id" = 3, "created" = E'2011-11-11 22:31:08.022148' WHERE "notification_notice"."id" = 14 

這就是我的表的樣子。創建的列的時區具有「-08」時區。 Postgres必須檢查我的系統時鐘的時區以查找時區。

my_db=# select * from notification_notice limit 1; 
id | sender_id | group_id | notice_type_id | content_type_id | object_id |   created   | last_interaction_time 
----+-----------+----------+----------------+-----------------+-----------+------------------------------+----------------------- 
    1 |   |  3 |    21 |    53 |   6 | 2011-11-11 14:31:02.98882-08 | 
(1 row) 

問題:
不Django的有放手政策時區?
爲什麼Postgres後端爲models.DateTimeField使用時區?這是Postgres需要的嗎?
有沒有辦法強制Django在Postgres中創建不使用時區的時間戳列?

+0

可能的答案:[here](http://stackoverflow.com/questions/1869419/django-datetime-field-to-generate-timestamp-fields-without-timezone/1869568#1869568) – unutbu

回答

16

壞消息是問題的根源在Python的日期時間實現中。

好消息是Django在這個問題上有an open ticket

的壞消息是,門票於2006年

開好消息是,recent proposal是比較有用的閱讀,似乎是在發展的。包含提案的主題很長,但內容非常豐富。

壞消息是,提案歸結爲「這是一個真正的混亂」。 (仍然在開發中)

我進一步發現Postgres後端指向Django創建使用時區的列 。

不,這是一個Django設計決定。 PostgreSQL只存儲UTC;它不存儲時區,也不存儲偏移量。時區在概念上就像一個環境變量,在插入或選擇檢索時應用於時間戳。

來自django developer's mail archive。 。 。

在數據庫中沒有實際的時區支持,Django在採取的任何行動 是要別人帶來不便,並可能會 不能與非Django中使用同一個數據庫的兼容。

這是一個很大的問題 - 一個可能使數據庫與其他語言或框架不兼容的問題。在我工作的地方,這是一個絕對的展示器。許多編程語言和框架訪問數據庫。在該線程中引用了SQLite,Microsoft Access和MySQL(日期時間數據類型,不是時間戳),因爲數據庫中缺少時區支持。

+0

是的我明白它是一個Django設計說明。通過「Postgres後端」,我指的是Django ORM的Postgres後端。 – hekevintran

+0

如果時區就像一個環境變量,那麼這是否意味着我只需要在我的數據庫連接中設置時區(例如UTC)? – hekevintran

+2

@hekevintran:我仍然在閱讀(再次)我發佈的那些引用。當我與時區和多個應用程序一起工作時,突然我的名字是「Alice」,我陷入了兔子洞:我不再確定我所知道的和我不知道的。我會說,「不」,因爲你的Django應用程序在存儲它們之前仍然需要將你的每一個時間戳標準化爲UTC。每一個,永遠。我也會說,「不」,因爲我很確定有一些微妙的點,我錯過了。也許我只是累了。 –

0

Postgresql能夠將時區與時區一起存儲的事實是一件好事。時間戳應該表示一個時間點。如果你閱讀「2013-03-15 14:38:00」,是否足以確切地知道代表什麼時間點?沒有!它可能在紐約14:38或在柏林14:38,這是兩個不同的時間點。所以,除非特定的時區被隱含(例如UTC),否則不應該有沒有時區的時間戳(它們被稱爲「天真」日期時間)。

Django創建帶時區的時間戳因此是好的在我看來。您可以覆蓋writing your own DatetimeField的默認行爲,但我不會推薦它,除非您有很好的理由擺脫數據庫中的時區(例如,因爲它打破了其他傳統程序)。

如果您使用Django < 1.4,那麼postgresql客戶端代碼將假定所有日期時間都在您系統的時區中。因此,如果您的django服務器的時區是柏林,那麼「2013-03-15 14:38:00」將在柏林時區解釋爲14:38,並且所有信息將存儲在數據庫中。如果您刪除時區信息,則在DST時間更改時您將遇到問題。例如,「2013-10-26 02:30:00」含糊不清:是凌晨2:30的第一次還是第二次?如果你走這條路線,你必須在你的Django代碼中將所有日期時間轉換爲UTC,並將UTC日期時間存儲在數據庫中。

如果您使用Django> = 1.4,那麼默認情況下它是時區感知的,並且期望每個日期時間都有一個時區。由於Python日期時間不幸的是而不是默認情況下有時區,所以您應該使用pytz package來確保您操作的每個日期時間都是可識別時區的。

Django documentation about timezones是一個很好的閱讀。

1

我認爲你有一個不正確的假設。 PostgreSQL does not store time zone information

對於timestamp with time zone,在內部存儲的數值總是UTC(協調世界時,習慣上稱爲格林威治標準時間,GMT)。使用該時區的適當偏移量將具有指定明確時區的輸入值轉換爲UTC。如果輸入字符串中沒有規定時區,則假定它位於系統的TimeZone參數指示的時區中,並使用時區區域的偏移量轉換爲UTC。

因此實際上,時區信息丟失。但時間瞬間保留

這意味着當您獲取時間戳信息時,無論您的服務器或服務器當前在哪個時區,都將始終正確。對於大多數應用程序,這正是你想要的。