add by zhj: 推薦使用標准庫中的dateutil代替pytz
原文:https://www.hongweipeng.com/index.php/archives/1803/
起步
在django框架中,用的是 pytz 庫處理時區問題,所以我也嘗試用這個庫來處理。但發現了一個奇怪的問題:
|
1
2
3
4
5
|
import
datetime
import
pytz
dt
=
datetime.datetime(
2019
,
6
,
20
,
12
, tzinfo
=
pytz.timezone(
'Asia/Shanghai'
))
print
(dt)
# 2019-06-20 12:00:00+08:06
|
為什么多出了 6 分鍾來?
原因
這是因為 pytz 里保存是本地時間。
|
1
2
3
|
fmt
=
'%Y-%m-%d %H:%M:%S %Z%z'
dt
=
datetime.datetime(
2019
,
6
,
20
,
12
, tzinfo
=
pytz.timezone(
'Asia/Shanghai'
))
print
(dt.strftime(fmt))
# 2019-06-20 12:00:00 LMT+0806
|
LMT 即 Local Mean Time 本地時間,也就是說 'Asia/Shanghai' 這個地區比utc多了8小時零6分鍾,並不是北京時間。
解決
所以 pytz 提供了 localize() 方法來糾正這個問題,但傳入的得是不帶時區的日期對象:
|
1
2
3
4
5
6
7
8
|
cn_zone
=
pytz.timezone(
'Asia/Shanghai'
)
dt
=
cn_zone.localize(dt
=
datetime.datetime(
2019
,
6
,
20
,
12
))
print
(dt)
# 2019-06-20 12:00:00+08:00
print
(dt.strftime(fmt))
# 2019-06-20 12:00:00 CST+0800
# 或者
dt
=
datetime.datetime(
2019
,
6
,
20
,
12
)
print
(dt.astimezone(cn_zone))
# 2019-06-20 12:00:00 CST+0800
|
這里推薦的還是用 astimezone 的方式,django 也是采用這種處理方式。
時區轉換
以從北京時間轉紐約時間為例,已知結果它們之間應該相差12小時。
|
1
2
3
4
|
dt
=
datetime.datetime(
2019
,
6
,
20
,
12
)
print
(dt.astimezone(tz
=
cn_zone))
# 2019-06-20 12:00:00+08:00
print
(dt.astimezone(tz
=
cn_zone).astimezone(ny_zone))
# 2019-06-20 12:00:00-04:56
|
額外
另一個解決時區問題就是使用標准庫的 dateutil 工具。官方內置,值得信賴。它支持在創建日期對象的時候進行設置,更為方便:
|
1
2
3
4
5
6
7
8
|
cn
=
tz.gettz(
'Asia/Shanghai'
)
aware_dt
=
datetime.datetime(
2019
,
6
,
20
,
12
, tzinfo
=
cn)
print
(aware_dt )
# 2019-06-20 12:00:00+08:00
# 時區轉換(從北京時間轉到紐約時間)
ny
=
tz.gettz(
'America/New_York'
)
print
(aware_dt.astimezone(tz
=
ny))
# 2019-06-20 00:00:00-04:00
|
我更喜歡這種方式。
