30
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

pytzを使ってpythonでタイムゾーンを扱う"正しい"方法

Last updated at Posted at 2019-07-04

各国のタイムゾーンを扱うpytz

Python のタイムゾーンと言えば pytz
Python 3 になって標準ライブラリに timezone が出来ましたが、便利な pytz もよく使います。

pytz
import pytz
tz = pytz.timezone('Asia/Tokyo')
timezone
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分ずれてるとかなんとか。

30
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?