since 2018-08-11
Python で日付や時刻(タイムゾーンなど)を扱うために pytz がよく使われる。
夏時間が終わるときに1日に2回同じローカルタイムが存在する。
それを区別するために is_dst がある。
from datetime import datetime import pytz e = pytz.timezone('US/Eastern') dt = datetime(2018,11,4, 1,30,0) print(e.localize(dt, is_dst=True).astimezone(pytz.utc)) # 2018-11-04 05:30:00+00:00 print(e.localize(dt, is_dst=False).astimezone(pytz.utc)) # 2018-11-04 06:30:00+00:00
引数を省略すると False と扱われるが None を明示的に指定すると例外になる。
e.localize(dt, is_dst=None) # => AmbiguousTimeError: 2018-11-04 01:30:00
django.utils.timezone の make_aware 関数の説明に出てくる
pandas の Timestamp.tz_localize
日本の1951年の夏時間も扱えている。やはり夏時間が終わるときにひとつのローカル時刻が2つのUTC時刻に対応する。
https://www.timeanddate.com/time/change/japan/tokyo?year=1951
j = pytz.timezone('Asia/Tokyo') dt = datetime(1951,9,8, 1,30,0) print(j.localize(dt, is_dst=True).astimezone(pytz.utc)) # 1951-09-07 15:30:00+00:00 print(j.localize(dt, is_dst=False).astimezone(pytz.utc)) # 1951-09-07 16:30:00+00:00
タイムゾーンは地域だけで決まらない。
現在の pytz では timezone('Asia/Tokyo') はデフォルトのオフセットが9時間19分になっている。
このへんが由来か
https://github.com/stub42/pytz/blob/master/tz/asia#L1512
バグではなく「仕様の厳格化」という話。
https://gist.github.com/a-hisame/85ed049d622f5a88c570c252f6611ff0
jst = pytz.timezone('Asia/Tokyo') print(jst.utcoffset) # <bound method DstTzInfo.utcoffset of <DstTzInfo 'Asia/Tokyo' LMT+9:19:00 STD>> t1 = datetime(2018,8,11, 9,0,0, tzinfo=jst) print(t1) # 2018-08-10 23:41:00+00:00 print(pytz.utc.normalize(t1)) # 2018-08-10 23:41:00+00:00
timezone インスタンスを特定の時刻でローカライズする、という手順で正しく変換できる。
t2 = datetime(2018,8,11, 9,0,0) print(jst.localize(t2)) # 2018-08-11 09:00:00+09:00 print(jst.localize(t2).astimezone(pytz.utc)) # 2018-08-11 00:00:00+00:00