はじめに
APIでスタンダードな日付形式であるISO8601について、Pythonで扱うのに軽くはまったのでメモ。
ISO8601形式は様々な書き方ができますが、有名どころのAPIでは以下の2種類が多いと思います。
-
UTC
- 2016-12-31T20:02:05.123456Z
-
APIのパラメータやサービスで設定したタイムゾーン
- 2016-12-31T20:02:05.123456+0900
文字列 -> datetime
APIからJsonで戻ってきた文字列をPythonのdatetimeに変換します。常にJSTで統一しています。
datetimeはそのまま、>, < での比較ができ、timedeltaによる日付の計算ができるため、プログラム内では常にdatetimeで表現するのがよいかと思います。
def iso_to_jstdt(iso_str):
dt = None
try:
dt = datetime.strptime(iso_str, '%Y-%m-%dT%H:%M:%S.%fZ')
dt = pytz.utc.localize(dt).astimezone(pytz.timezone("Asia/Tokyo"))
except ValueError:
try:
dt = datetime.strptime(iso_str, '%Y-%m-%dT%H:%M:%S.%f%z')
dt = dt.astimezone(pytz.timezone("Asia/Tokyo"))
except ValueError:
pass
return dt
datetime -> 表示用文字列
datetimeを画面なりに出力する文字列に変換します。
ここでは"/"区切りの日本風です。上記の関数でdatetimeにしてあれば日本時間で表示されます。
def dt_to_str(dt):
if dt is None:
return ''
return dt.strftime('%Y/%m/%d %H:%M:%S')
datetime -> ISO文字列
次のプログラムとのI/Fなど、親システム的にするにはISO形式で出力しておくとよいでしょう。
def dt_to_isostr(dt):
if dt is None:
return ''
return dt.isoformat()
example
上記変換処理の実行例です。
ここでは不正なフォーマットはNone,空文字で表現していますが、場合によっては最小の日付、最大の日付などで表現するという方法もありますね。
●サンプルプログラム
print('test1----------------------------')
dt1 = iso_to_jstdt('2016-12-31T20:02:05.123456Z')
print(dt1)
print(dt_to_str(dt1))
print(dt_to_isostr(dt1))
print('test2----------------------------')
dt2 = iso_to_jstdt('2016-12-31T20:02:05.123456+0900')
print(dt2)
print(dt_to_str(dt2))
print(dt_to_isostr(dt2))
print('test3----------------------------')
dt3 = iso_to_jstdt('2016-12-31T20:02:05.123456-0300')
print(dt3)
print(dt_to_str(dt3))
print(dt_to_isostr(dt3))
print('test4----------------------------')
dt4 = iso_to_jstdt('2016/12/31T20:02:05.123456Z')
print(dt4)
print(dt_to_str(dt4))
print(dt_to_isostr(dt4))
print('--------------------------------')
●実行結果
test1----------------------------
2017-01-01 05:02:05.123456+09:00
2017/01/01 05:02:05
2017-01-01T05:02:05.123456+09:00
test2----------------------------
2016-12-31 20:02:05.123456+09:00
2016/12/31 20:02:05
2016-12-31T20:02:05.123456+09:00
test3----------------------------
2017-01-01 08:02:05.123456+09:00
2017/01/01 08:02:05
2017-01-01T08:02:05.123456+09:00
test4----------------------------
None
--------------------------------
おわりに
Pythonに限らずですが、日付・時刻の扱いは面倒です。
終わりだよ~