Pythonのタイムゾーンの扱い

1 min read読了の目安(約1400字

環境: Python-3.5

Pythonの時刻はタイムゾーンを意識して作られている。タイムゾーンの扱いに関してのメモ。
timezone-naiveがタイムゾーンを意識してない時刻,timezone-awareがタイムゾーンを意識した時刻となる。

from datetime import datetime,timezone
import  pytz

naive = datetime.now()
aware = datetime.now(timezone.utc)

timezone#nowの引数にtimezoneを渡すとtimezone-awareな現在時刻が作られる。
この二つは比較できない。

naive > awre 
# TypeError: can't compare offset-naive and offset-aware datetimes

例外がスローされる。

任意の時刻を作るときには以下のようにしてtimezoneを引数に渡す。

naive = datetime(2016,6,1,12,0,0,0)
aware = datetime(2016,6,1,12,0,0,0,timezone.utc)

ローカルのタイムゾーンに変更したいときにはdatetime#astimezoneを使う。
当然timezone-naiveな時刻は使えない。

print(naive.astimezone())
# ValueError: astimezone() cannot be applied to a naive datetime
print(aware.astimezone())
# 2016-06-01 21:00:00+09:00

自分の好きなタイムゾーンを使うときにはpytzを使うと便利。
timezone-naiveな時刻を指定したタイムゾーンに変更する。

import  pytz

de = pytz.timezone('Europe/Berlin')
print(de.localize(naive))
# 2016-06-01 12:00:00+02:00

jp = pytz.timezone('Asia/Tokyo')
print(jp.localize(naive))
# 2016-06-01 12:00:00+09:00

timezone-awareな時刻のタイムゾーンを変更する。
これは実際の時刻が変更されるわけではない。

print(aware.astimezone(jp))
# 2016-06-01 21:00:00+09:00
print(aware.astimezone(de))
# 2016-06-01 14:00:00+02:00

datetime#replaceでタイムゾーンを上書きできる。当然表現する時刻が変わってしまう。

print(aware.replace(tzinfo=jp).astimezone(timezone.utc))
# 2016-06-01 03:00:00+00:00
print(aware.replace(tzinfo=de).astimezone(timezone.utc))
# 2016-06-01 11:07:00+00:00