Django中的時區


Django的settings配置中有一個USE_TZ項,默認值為True。很多人不太清楚這個配置項具體是干什么的,只知道和時區有關。下面我們就來詳細聊聊它。

首先,我們要了解一下什么是offset-awareoffset-navie

offset-aware與offset-navie

在Python中,有一個datetime模塊,相信大家都很熟悉。但是很少有人知道這個模塊的時間還可以分下面兩種類型:

  • offset-naive:不含時區的類型
  • offset-aware:有時區的類型

並且,這兩種類型的時間是不可以直接比較的,比如做減法、加法、時間對比等,會拋出下面的異常:

TypeError: can't compare offset-naive and offset-aware datetimes

根本的原因在於兩者一個有時區信息,一個沒有。

我們可以通過查看datetime對象的tzinfo屬性,來判斷具體是兩者中的哪種:

>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2020, 5, 26, 18, 36, 59, 811729)
>>> now.tzinfo
>>> now.tzinfo==None
True

可以很清楚的看到,datetime.datetime.now()是一個offset-naive類型,不含時區信息的時間對象。

我們可以借助pytz模塊,將一個offset-naive類型的時間對象轉換為一個offset-aware類型的時間對象。

先安裝pytz模塊:

pip install pytz

來測試一下:

>>> import pytz
>>> now = now.replace(tzinfo=pytz.timezone('UTC'))
>>> now
datetime.datetime(2020, 5, 26, 18, 36, 59, 811729, tzinfo=<UTC>)
>>> now.tzinfo
<UTC>

反過來,也可以將一個offset-aware型轉換為offset-naive型:

>>> now = now.replace(tzinfo=None)
>>> now
datetime.datetime(2020, 5, 26, 18, 36, 59, 811729)
>>> now.tzinfo == None
True

USE_TZ配置

回到Django種來。我們知道,在安裝Django的同時,默認會安裝一個pytz模塊,然后在django.utils下就會有一個timezone模塊,其實它就是pytz.timezone

首先,我們要清楚一件事。Django的settings配置中的USE_TZ默認值為True,也就是說,默認情況下Django數據庫里面存儲的日期數據是帶時區信息的,也就是offset-aware類型。

這就導致了我們有些時候,進行時間對比或者加減的操作,會拋出前面說的異常。

TypeError: can't compare offset-naive and offset-aware datetimes

那怎么辦呢?

最原始朴素的方法,自然是對時間類型進行轉換,采用上面的例子中的方法,統一起來,就可以進行比較了。

還有一種更簡單的方法,那就是將USE_TZ設置為False。此時,數據庫里保存的時間對象就不在包含時區信息了,和原生的datetime.datetime是一種類型,都是offset-naive類型,自然不會發生沖突。

Tips:應該在項目開始之初,創建數據表之前就設置USE_TZ為False,否則先前保存的時間數據可能依然帶有時區信息。

其實,還有一種更適用的方法,就是USE_TZ依然保持為True,但是不再使用datetime庫了,而是使用timezone來獲取now時間:

from django.utils import timezone  
  
now = timezone.now()

這樣,大家都帶有時區信息,自然也是可以比較的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM