Подтвердить что ты не робот

Объект ISO to 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.

4b9b3361

Ответ 1

Добро пожаловать в Python datetime! Работа с датами и временем обязательно сложна, и Python не поставляется полностью с батареями, включенными в этот случай. Вы не можете использовать %z в strptime, потому что у Python нет классов для представления часовых поясов (вы должны реализовать свои собственные или, еще лучше, включить некоторые другие библиотеки).

Вы хотите использовать pytz и python-dateutil. Подробнее см. Здесь:

Python strptime() и часовые пояса?

Ответ 2

проблема с python 2.7

У меня была аналогичная проблема с обработкой дат фиксации из вывода git log --date=iso8601, который фактически не является форматом 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:

Если python 2 не поддерживает %z из-за базовой реализации strptime(), тогда возможный способ исправить вашу проблему - перенести на 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 singleton.

без 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, поддержка отсутствует.