Give AlbumentationsX a star on GitHub — it powers this leaderboard

Star on GitHub

ciso8601

Fast ISO8601 date time parser for Python written in C

Rank: #1103Downloads: 11,523,461 (30 days)Stars: 574Forks: 49

Description

========
ciso8601
========

.. image:: https://img.shields.io/circleci/project/github/closeio/ciso8601.svg
    :target: https://circleci.com/gh/closeio/ciso8601/tree/master

.. image:: https://img.shields.io/pypi/v/ciso8601.svg
    :target: https://pypi.org/project/ciso8601/

.. image:: https://img.shields.io/pypi/pyversions/ciso8601.svg
    :target: https://pypi.org/project/ciso8601/

``ciso8601`` converts `ISO 8601`_ or `RFC 3339`_ date time strings into Python datetime objects.

Since it's written as a C module, it is much faster than other Python libraries.
Tested with cPython 2.7, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14.

.. _ISO 8601: https://en.wikipedia.org/wiki/ISO_8601
.. _RFC 3339: https://tools.ietf.org/html/rfc3339

(Interested in working on projects like this? `Close`_ is looking for `great engineers`_ to join our team)

.. _Close: https://close.com
.. _great engineers: https://jobs.close.com


.. contents:: Contents


Quick start
-----------

.. code:: bash

  % pip install ciso8601

.. code:: python

  In [1]: import ciso8601

  In [2]: ciso8601.parse_datetime('2014-12-05T12:30:45.123456-05:30')
  Out[2]: datetime.datetime(2014, 12, 5, 12, 30, 45, 123456, tzinfo=pytz.FixedOffset(330))

  In [3]: ciso8601.parse_datetime('20141205T123045')
  Out[3]: datetime.datetime(2014, 12, 5, 12, 30, 45)

Migration to v2
---------------

Version 2.0.0 of ``ciso8601`` changed the core implementation. This was not entirely backwards compatible, and care should be taken when migrating
See `CHANGELOG`_ for the Migration Guide.

.. _CHANGELOG: https://github.com/closeio/ciso8601/blob/master/CHANGELOG.md

When should I not use ``ciso8601``?
-----------------------------------

``ciso8601`` is not necessarily the best solution for every use case (especially since Python 3.11). See `Should I use ciso8601?`_

.. _`Should I use ciso8601?`: https://github.com/closeio/ciso8601/blob/master/why_ciso8601.md

Error handling
--------------

Starting in v2.0.0, ``ciso8601`` offers strong guarantees when it comes to parsing strings.

``parse_datetime(dt: String): datetime`` is a function that takes a string and either:

* Returns a properly parsed Python datetime, **if and only if** the **entire** string conforms to the supported subset of ISO 8601
* Raises a ``ValueError`` with a description of the reason why the string doesn't conform to the supported subset of ISO 8601

If time zone information is provided, an aware datetime object will be returned. Otherwise, a naive datetime is returned.

Benchmark
---------

Parsing a timestamp with no time zone information (e.g., ``2014-01-09T21:48:00``):

.. <include:benchmark_with_no_time_zone.rst>

.. table::

    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |             Module             |Python 3.14|Python 3.13|Python 3.12|Python 3.11|Relative slowdown (versus ciso8601, latest Python)|…|Python 3.10|Python 3.9|Python 3.8|
    +================================+===========+===========+===========+===========+==================================================+=+===========+==========+==========+
    |ciso8601                        |26.4 nsec  |23.4 nsec  |24.5 nsec  |25.4 nsec  |N/A                                               |…|35.9 nsec  |35.6 nsec |37 nsec   |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |backports.datetime_fromisoformat|N/A        |N/A        |N/A        |N/A        |0.8x                                              |…|30.3 nsec  |30.7 nsec |32 nsec   |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |datetime (builtin)              |51.5 nsec  |48 nsec    |54.8 nsec  |53.9 nsec  |2.0x                                              |…|N/A        |N/A       |N/A       |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |udatetime                       |269 nsec   |277 nsec   |277 nsec   |280 nsec   |10.2x                                             |…|280 nsec   |279 nsec  |280 nsec  |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |str2date                        |1.4 usec   |1.42 usec  |1.59 usec  |1.59 usec  |52.9x                                             |…|1.62 usec  |1.64 usec |1.76 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |pendulum                        |1.74 usec  |65.2 nsec  |64.8 nsec  |64.7 nsec  |65.8x                                             |…|64.6 nsec  |66.4 nsec |86.4 nsec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |iso8601                         |2.13 usec  |2.2 usec   |2.35 usec  |2.1 usec   |80.6x                                             |…|2.3 usec   |2.31 usec |2.47 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |iso8601utils                    |N/A        |N/A        |N/A        |N/A        |61.5x                                             |…|N/A        |2.19 usec |2.51 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |isodate                         |2.36 usec  |2.52 usec  |2.78 usec  |2.18 usec  |89.3x                                             |…|2.41 usec  |2.4 usec  |2.49 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |PySO8601                        |3.55 usec  |3.79 usec  |3.79 usec  |3.11 usec  |134.6x                                            |…|3.94 usec  |3.64 usec |6.79 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |aniso8601                       |4.32 usec  |4.74 usec  |4.95 usec  |4.37 usec  |163.9x                                            |…|5.53 usec  |5.19 usec |5.72 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |zulu                            |4.71 usec  |4.63 usec  |5.12 usec  |4.54 usec  |178.7x                                            |…|5.17 usec  |4.93 usec |5.17 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |python-dateutil                 |10.3 usec  |11.4 usec  |12.6 usec  |11.9 usec  |390.4x                                            |…|14.9 usec  |15.3 usec |15.8 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |arrow                           |13.3 usec  |13.4 usec  |14.7 usec  |13.5 usec  |503.5x                                            |…|16.7 usec  |16.2 usec |17.4 usec |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |maya                            |13.7 usec  |10.9 usec  |14.7 usec  |12.7 usec  |520.0x                                            |…|15.7 usec  |14.5 usec |16 usec   |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |metomi-isodatetime              |335 usec   |345 usec   |353 usec   |359 usec   |12687.0x                                          |…|480 usec   |468 usec  |508 usec  |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |moment                          |487 usec   |502 usec   |525 usec   |503 usec   |18471.2x                                          |…|563 usec   |559 usec  |576 usec  |
    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+

ciso8601 takes 26.4 nsec, which is **2.0x faster than datetime (builtin)**, the next fastest Python 3.14 parser in this comparison.

.. </include:benchmark_with_no_time_zone.rst>

Parsing a timestamp with time zone information (e.g., ``2014-01-09T21:48:00-05:30``):

.. <include:benchmark_with_time_zone.rst>

.. table::

    +--------------------------------+-----------+-----------+-----------+-----------+--------------------------------------------------+-+-----------+----------+----------+
    |             Module             |Python 3.14|Python 3.13|Python 3.12|Python 3.11|Relative slowdown (versus ciso8601, latest Python)|…|Python 3.10|Python 3.9|Python 3.8|
    +================================+===========+===========+===========+===========+==================================================+=+===========+==========+==========+
    |ciso8601