各国のタイムゾーンを扱うpytz
Python のタイムゾーンと言えば pytz
Python 3 になって標準ライブラリに timezone が出来ましたが、便利な pytz もよく使います。
import pytz
tz = pytz.timezone('Asia/Tokyo')
from datetime import timedelta, timezone
tz = timezone(timedelta(hours=+9), 'Asia/Tokyo')
(速度を求める場合は timezone を使うのがいいみたいです)
参考:Python3のdatetimeはタイムゾーンを指定するだけで高速になる
この便利な pytz も正しく使わないとJSTが19分ずれたりして困る(後述)ので、正しい使い方をメモ代わりに書き残します。
といっても公式ドキュメントに書いてあることほぼそのままの記事です。
pytzドキュメント (PyPI)
インストール
pip install pytz
使い方
naive な datetime インスタンス(タイムゾーン情報を持たない datetime インスタンス)にタイムゾーン情報を付与する際には localize() メソッドを使います。
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
aware な datetime インスタンス(タイムゾーン情報を持つ datetime インスタンス)のタイムゾーンを変換する際には datetime の astimezone() メソッドを使います。
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になっていますね。
サマータイムなどの特殊なタイムゾーン情報を持った datetime インスタンスを操作(進めたり戻したり)した後は normalize() メソッドを使ってタイムゾーン情報を正しいものに更新します。
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 を除いて、datetime のコンストラクタに pytz 由来の timezone (tzinfo) は渡してはいけません。サマータイムなどの特殊な日時計算が正しく動作しないためです。
Asia/Tokyo のタイムゾーンでも +09:19 になってしまいます。
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年より前は各都市毎に時間が決められていて、Asia/Tokyo というのはまさしく(現在のように明石基準でなく)東京基準の時間だったので、19分ずれてるとかなんとか。