python - Objeto ISO a datetime: ''z'' es una mala directiva
rfc3339 (2)
Esta pregunta ya tiene una respuesta aquí:
Estoy tratando de convertir ISO a datetime
y datetime
usando el siguiente código:
dt = datetime.datetime.strptime("2013-07-23T15:10:59.342107+01:00",
"%Y-%m-%dT%H:%M:%S.%f%z")
y obtengo el siguiente error:
''z'' is a bad directive in format ''%Y-%m-%dT%H:%M:%S.%f%z''
¿Cuál es la mejor manera de convertir una cadena ISO de encima del formato a un objeto datetime
? Estoy usando Python versión 2.7.6.
problema con Python 2.7
He tenido un problema similar al analizar las fechas de confirmación de la salida de git log --date=iso8601
que en realidad no es el formato ISO8601 (de ahí la adición de --date=iso8601-strict
en una versión posterior).
>>> 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)]''
problema con python 3:
Si python 2 no es compatible con %z
debido a la strptime()
subyacente de strptime()
, entonces una posible forma de solucionar el problema es migrar a python 3. Pero no funcionó para mí:
>>> 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)]''
El problema es porque no es estrictamente ISO8601 (tenga en cuenta cómo había una :
en la información de la zona horaria).
>>> 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)))
solución con django y pytz:
Como uso django
, puedo aprovechar las utilidades allí.
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)
En lugar de strptime
puedes usar tu propia expresión regular.
Tenga en cuenta que django usa pytz
debajo del capó para cosas como utc
singleton.
solución sin django y pytz:
Si quieres una solución rápida y sucia, puedes usar algo similar a django
sin todos los requisitos.
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)
Tenga en cuenta: YMMV, no hay soporte.
Bienvenido a Python datetime! Tratar con las fechas y los tiempos es necesariamente complejo, y Python no cuenta con baterías incluidas en este caso. No puede usar %z
en strptime
porque Python no tiene clases para representar las zonas horarias (se supone que debe implementar las suyas, o mejor aún incluir algunas otras bibliotecas).
Desea usar pytz
y python-dateutil
. Para más detalles ver aquí: