web-dev-qa-db-ja.com

ISOからdatetimeオブジェクト: 'z'は悪いディレクティブです

以下のコードを使用して、ISOをdatetimeに変換しようとしています。

dt = datetime.datetime.strptime("2013-07-23T15:10:59.342107+01:00",
                                "%Y-%m-%dT%H:%M:%S.%f%z")

そして、私は以下のエラーを取得しています:

'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S.%f%z'

上記の形式のISO文字列をdatetimeオブジェクトに変換する最良の方法は何ですか?私はPythonバージョン2.7.6を使用しています。

38
user2667326

Python datetimeへようこそ!日付と時刻の処理は必然的に複雑であり、Pythonはこの場合に含まれるバッテリーを完全には備えていません。 Pythonにはタイムゾーンを表すクラスがないため、strptime%zを使用することはできません(独自に実装するか、他のライブラリを含めることをお勧めします)。

pytzpython-dateutilを使用します。詳細については、こちらをご覧ください。

Python strptime()およびタイムゾーン?

24
Max

python 2.7の問題

実際にISO8601形式ではない_git log --date=iso8601_の出力からのコミット日付の解析で同様の問題が発生しました(したがって、後のバージョンで_--date=iso8601-strict_が追加されました)。

_>>> import datetime, sys
>>> datetime.datetime.strptime("2013-07-23T15:10:59.342107+01:00", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 317, in _strptime
    (bad_directive, format))
ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S.%f%z'
>>> sys.version
'2.7.10 (default, Feb  7 2017, 00:08:15) \n[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]'
_

python 3の問題:

基になるstrptime()実装のためにpython 2が_%z_をサポートしていない場合、問題を解決する可能な方法はpython 3に移行することですしかし、それは私にとってはうまくいきませんでした:

_>>> import datetime, sys
>>> datetime.datetime.strptime("2013-07-23T15:10:59.342107+01:00", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_strptime.py", line 565, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_strptime.py", line 362, in _strptime
    (data_string, format))
ValueError: time data '2013-07-23T15:10:59.342107+01:00' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
>>> sys.version
'3.6.3 (v3.6.3:2c5fed86e0, Oct  3 2017, 00:32:08) \n[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]'
_

問題は、厳密にはISO8601ではないためです(タイムゾーン情報に_:_があったことに注意してください)。

_>>> datetime.datetime.strptime("2013-07-23T15:10:59.342107+0100", "%Y-%m-%dT%H:%M:%S.%f%z")
datetime.datetime(2013, 7, 23, 15, 10, 59, 342107, tzinfo=datetime.timezone(datetime.timedelta(0, 3600)))
_

Djangoおよびpytzを使用したソリューション:

Djangoを使用しているので、そこでユーティリティを活用できます。

https://github.com/Django/django/blob/master/Django/utils/dateparse.py

_>>> from Django.utils.dateparse import parse_datetime
>>> parse_datetime('2013-07-23T15:10:59.342107+01:00')
datetime.datetime(2013, 7, 23, 15, 10, 59, 342107, tzinfo=+0100)
_

strptimeの代わりに、独自の正規表現を使用できます。

Djangoはpytzシングルトンのようなもののためにフードの下でutcを使用することに注意してください。

Djangoおよびpytzなしのソリューション:

迅速で汚れたソリューションが必要な場合は、Djangoに似たものをすべての要件なしで使用できます。

https://Gist.github.com/dnozay/3cd554a818ed768bff804bc04484905d

_>>> from datetime_z import parse_datetime
>>> parse_datetime("2013-07-23T15:10:59.342107+01:00")
datetime.datetime(2013, 7, 23, 15, 10, 59, 342107, tzinfo=+0100)
_

注:YMMV、サポートはありません。

22
dnozay