strftime() と strptime() を使ってtzinfo付きdatetime <-> stringの変換をやってみた


環境

Python 2.7.10

参考資料

8.1. datetime — 基本的な日付型および時間型

strftimeを使ってtzinfoを保持したdatetime文字列を取得

>>> from datetime import datetime
>>> import pytz
>>> 
>>> jst = pytz.timezone('Japan')
>>> jst_datetime = datetime.now().replace(tzinfo=jst)
>>> print jst_datetime
2015-11-12 16:09:18.544266+09:00
>>> jst_datetime_str = datetime.strftime(jst_datetime, '%Y-%m-%d %H:%M:%S %z')
>>> print jst_datetime_str
2015-11-12 16:09:18 +0900
>>> datetime.strftime(jst_datetime, '%Y-%m-%d %H:%M:%S %Z')
'2015-11-12 16:09:18 JST'

tzinfo付きdatetime文字列を出力する事が出来る。

strptimeを使ってdatetime文字列からtzinfo付きdatetimeを取得

>>> print jst_datetime_str
2015-11-12 16:09:18 +0900
>>> datetime.strptime(jst_datetime_str, '%Y-%m-%d %H:%M:%S %z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/lib/python2.7/_strptime.py", line 317, in _strptime
    (bad_directive, format))
ValueError: 'z' is a bad directive in format '%Y-%m-%d %H:%M:%S %z'
>>> 

tzinfo付きdatetime文字列を使ってtimsezone付きdatetimeを取得しようとしたのだがエラー。

ValueError: 'z' is a bad directive in format '%Y-%m-%d %H:%M:%S %z'

'%z'指定子が悪いフォーマットだぞ的なエラーが発生する。

色々調べてみた結果
http://stackoverflow.com/questions/2609259/converting-string-to-datetime-object-in-python

python2.7では%zはサポートされていないよう。python3.2なら動くらしい。
バージョン変える事が出来ないので他の方法を試す

>>> jst_datetime_str = datetime.strftime(jst_datetime, '%Y-%m-%d %H:%M:%S %Z')
>>> print jst_datetime_str
2015-11-12 16:09:18 JST
>>> datetime.strptime(jst_datetime_str, '%Y-%m-%d %H:%M:%S %Z')
datetime.datetime(2015, 11, 12, 16, 9, 18)

%Zを使ってやってみたのだが、今度はエラーは発生しないもののtzinfoが付いてないdatetimeが出来てしまう。

他を探してみると
http://nekoya.github.io/blog/2013/06/21/python-datetime/

この人も、%Zを使ってだめだったので「replace(tzinfo=pytz.utc)」を使って設定しているようだ。
指定子を使用して変換するのはもう無理そうなので、ごり押しで対応してみた

>>> from datetime import datetime
>>> import pytz
>>> 
>>> jst = pytz.timezone('Japan')
>>> jst_datetime = datetime.now().replace(tzinfo=jst)
>>> print jst_datetime
2015-11-12 16:54:19.564920+09:00
>>> jst_datetime_str = datetime.strftime(jst_datetime, '%Y-%m-%d %H:%M:%S') + ' ' + jst_datetime.tzinfo.zone
>>> print jst_datetime_str
2015-11-12 16:54:19 Japan
>>> zone = jst_datetime_str.split(' ')[-1]
>>> print zone
Japan
>>> datetime_str = ' '.join(jst_datetime_str.split(' ')[:2])
>>> print datetime_str
2015-11-12 16:54:19
>>> datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.timezone(zone))
datetime.datetime(2015, 11, 12, 16, 54, 19, tzinfo=<DstTzInfo 'Japan' JST+9:00:00 STD>)

こんな感じ。

まとめ

・python2.7だとstrptimeで指定子 '%Z'と'%z'は使えない。
・ただ、strftimeでは正常に使える。
・後、確認はしてないがpython3.2だとstrptimeでも使えるようだ。
・正直相当無理矢理な感じだけど、他にいい方法ないのかな。