使用pytz处理python中时区的”正确”方法


涉及每个国家时区的Pytz

说到Python时区,pytz
既然Python 3在标准库中有时区,我也经常使用方便的pytz。

pytz

1
2
import pytz
tz = pytz.timezone('Asia/Tokyo')

时区

1
2
from datetime import timedelta, timezone
tz = timezone(timedelta(hours=+9), 'Asia/Tokyo')

(如果要提高速度,最好使用时区)。
参考:仅通过指定时区

,Python3 datetime更快

如果您没有正确使用此方便的pytz,JST将在19分钟后关闭(稍后介绍),因此我将写下正确的用法,而不是备忘。

即使

是几乎与官方文档中所写内容完全相同的文章。
pytz文件(PyPI)

安装

1
pip install pytz

如何使用

使用localize()方法将时区信息提供给

天真日期时间实例(不具有时区信息的日期时间实例)。

1
2
3
4
5
6
7
8
9
from datetime import datetime, timedelta
import pytz

tokyo = pytz.timezone('Asia/Tokyo')

tokyo_datetime = tokyo.localize(datetime(2019, 7, 7, 14, 12, 34))

print(tokyo_datetime)
# 2019-07-07 14:12:34+09:00

使用datetime的astimezone()方法可以转换

感知日期时间实例(具有时区信息的datetime实例)的时区。

1
2
3
4
5
6
london = pytz.timezone('Europe/London')

london_datetime = tokyo_datetime.astimezone(london)  # Asia/Tokyo から Europe/London へ変換

print(london_datetime)
# 2019-07-07 06:12:34+01:00

伦敦是UTC 0,但它是UTC 1,因为它在夏令时期间。

在操纵(前进或后退)具有特殊时区信息(例如夏时制)的日期时间实例后,请使用normalize()方法将时区信息更新为正确的时区信息。

1
2
3
4
5
6
7
8
9
london_datetime += timedelta(weeks=24)  # 約6ヶ月後のロンドンの日時

print(london_datetime)
# 2019-12-22 06:12:34+01:00  12月なのにサマータイムのUTC+1になっている

london_datetime = london.normalize(london_datetime)

print(london_datetime)
# 2019-12-22 05:12:34+00:00

NG写作风格

除UTC之外,请勿将pytz派生的时区(tzinfo)传递给datetime构造函数。这是因为特殊的日期和时间计算(例如夏时制)无法正常工作。
即使在亚洲/东京时区,也将是09:19。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from datetime import datetime
import pytz

tokyo = pytz.timezone('Asia/Tokyo')

japan_dt = datetime(2019, 7, 7, 12, 24, 45, tzinfo=tokyo)  # NG(datetimeのコンストラクタに渡してはいけない)
print(japan_dt)
# 2019-07-07 12:24:45+09:19

japan_dt = tokyo.localize(datetime(2019, 7, 7, 12, 24, 45))  # OKな例
print(japan_dt)
# 2019-07-07 12:24:45+09:00

utc_dt = datetime(2019, 7, 7, 12, 24, 45, tzinfo=pytz.utc)  # UTCはOK
print(utc_dt)
# 2019-07-07 12:24:45+00:00

在1888年之前,日本标准时间被强制执行,每个城市都设置了时间,而亚洲/东京正是基于东京的时间(现在不是明石标准),不知怎的,现在是19分钟。