構建時區感知日期時間

預設情況下,所有 datetime 物件都是天真的。要使它們能夠識別時區,必須附加 tzinfo 物件,該物件提供 UTC 偏移和時區縮寫作為日期和時間的函式。

固定偏移時區

對於與 UTC 固定偏移的時區,在 Python 3.2+中,datetime 模組提供 timezone 類,tzinfo 的具體實現,它採用 timedelta 和(可選)名稱引數:

Python 3.x >= 3.2

from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9))

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00

print(dt.tzname())
# UTC+09:00

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST'))
print(dt.tzname)
# 'JST'

對於 3.2 之前的 Python 版本,必須使用第三方庫,例如 dateutildateutil 提供了一個等價的類 tzoffset,它(從版本 2.5.3 開始)接受 dateutil.tz.tzoffset(tzname, offset) 形式的引數,其中 offset 以秒為單位指定:

Python 3.x < 3.2

Python 2.x < 2.7

from datetime import datetime, timedelta
from dateutil import tz

JST = tz.tzoffset('JST', 9 * 3600) # 3600 seconds per hour
dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname)
# 'JST'

夏令時的區域

對於具有夏令時的區域,python 標準庫不提供標準類,因此必須使用第三方庫。 pytzdateutil 是提供時區類的熱門庫。

除靜態時區外,dateutil 還提供使用夏令時的時區類(請參閱 tz 模組的文件 )。你可以使用 tz.gettz() 方法獲取時區物件,然後可以將其直接傳遞給 datetime 建構函式:

from datetime import datetime
from dateutil import tz
local = tz.gettz() # Local time
PT = tz.gettz('US/Pacific') # Pacific time

dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # I am in EST
dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT)
dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST is handled automatically
print(dt_l)
# 2015-01-01 12:00:00-05:00
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-07-01 12:00:00-07:00

注意 :從版本 2.5.3 開始,dateutil 無法正確處理模糊日期時間,並且始終預設為較晚的日期。沒有辦法構造一個具有 dateutil 時區的物件,例如 2015-11-01 1:30 EDT-4,因為這是夏令時轉換期間。

使用 pytz 時,所有的邊緣案件得到妥善處理,但 pytz 時區應該不是通過建構函式直接連線到時區。相反,應使用時區的 localize 方法附加 pytz 時區:

from datetime import datetime, timedelta
import pytz

PT = pytz.timezone('US/Pacific')
dt_pst = PT.localize(datetime(2015, 1, 1, 12))
dt_pdt = PT.localize(datetime(2015, 11, 1, 0, 30))
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-11-01 00:30:00-07:00

請注意,如果在支援 pytz 的時區上執行日期時算術,則必須以 UTC 格式執行計算(如果需要絕對經過時間),或者必須在結果上呼叫 normalize()

dt_new = dt_pdt + timedelta(hours=3) # This should be 2:30 AM PST
print(dt_new)
# 2015-11-01 03:30:00-07:00
dt_corrected = PT.normalize(dt_new)
print(dt_corrected)
# 2015-11-01 02:30:00-08:00