Преобразование ISO-даты из строки в объект datetime.datetime (или datetime.date), наверное, одна из самых распространенных и постоянных задач в web-разработке на Python. Количество способов сделать это просто поражает воображение,
In [1]: value = '2017-06-28T16:59:27+0000'
In [2]: import datetime
In [3]: datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')
Out[3]: datetime.datetime(2017, 6, 28, 16, 59, 27, tzinfo=datetime.timezone.utc)
In [4]: from dateutil.parser import parse
In [5]: parse(value)
Out[5]: datetime.datetime(2017, 6, 28, 16, 59, 27, tzinfo=tzutc())
In [6]: import dateparser
In [7]: dateparser.parse(value)
Out[7]: datetime.datetime(2017, 6, 28, 16, 59, 27, tzinfo=)
Использовались функции: datetime.datetime.strptime, dateutil.parser.parse и dateparser.parse.
А ведь еще есть,
In [8]: import arrow
In [9]: arrow.get(value, 'YYYY-MM-DDTHH:mm:ssZZ')
Out[9]: <Arrow [2017-06-28T16:59:27+00:00]>
In [10]: import maya
In [11]: maya.parse(value)
Out[11]: <MayaDT epoch=1498669167.0>
-//-: arrow.get и maya.parse.
И это только вершина айсберга, потому что библиотек для работ с датами в Python не просто много, а очень много (что говорить, если у Django вообще есть своя parse_datetime функция, основанная на регекспе). У той или иной библиотеки работы с датами есть свои плюсы и особенности, но что делать, если нужно быстро конвертировать строки с датами в стандартные объекты datetime.datetime
? Как всегда ответ прост: использовать что-то написанное на C с биндингами в Python, в нашем случае - это ciso8601,
In [12]: ciso8601.parse_datetime(value)
Out[12]: datetime.datetime(2017, 6, 28, 16, 59, 27, tzinfo=)
Результаты %timeit
- красноречивы,
In [13]: %timeit datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')
17.9 µs ± 516 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [14]: %timeit parse(value)
99 µs ± 1.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [15]: %timeit dateparser.parse(value)
1.61 ms ± 39.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [16]: %timeit ciso8601.parse_datetime(value)
2.08 µs ± 67.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Итого: Если нужно быстро парсить ISO даты: используйте ciso8601.parse_datetime
, если нужно быстро парсить не ISO даты: сначала попробуйте стандартный datetime.datetime.strptime
, потом dateutil.parser.parse
и только в случае особой и острой необходимости dateparser.parse
и прочие библиотеки, основанные на нем.
ps. Результаты приведены для Python 3.6.1, на Python 2.7.13 соблюдаются такие же показатели, но в 2.7.13 в стандартном strptime
не было возможности разобрать +0000
, потому что ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S%z'
.