Fast ISO8601 Datetime Parser
ciso8601 is a Python library providing a highly optimized C extension for parsing ISO 8601 and RFC 3339 datetime strings into Python `datetime` objects. It is designed for maximum performance, often outperforming other Python date parsing libraries. The current version is 2.3.3, and it maintains an active release cadence with regular updates for new Python versions and bug fixes.
Warnings
- breaking Version 2.0.0 introduced significant changes to the core implementation that were not entirely backwards compatible. Users upgrading from pre-2.0.0 versions should consult the `CHANGELOG` for migration guidance.
- breaking In v2.3.0, the `FixedOffset`'s `dst`, `tzname`, and `utcoffset` methods no longer accept arguments, removing an improper ability that existed in previous versions.
- gotcha Versions prior to 2.3.3 contained a memory leak in the `FixedOffset_fromutc` function, particularly when dealing with timezone-aware datetimes.
- gotcha ciso8601 only supports a common subset of the ISO 8601 specification. For example, it only supports the HYPHEN-MINUS (`-`) character for timezone separators, not MINUS SIGN (`−`).
- gotcha When installing ciso8601 on systems without pre-built wheels, compilation from source is required. This necessitates having a C compiler (e.g., GCC on Linux, MSVC on Windows) and Python development headers (e.g., `python3-dev` on Debian/Ubuntu) installed.
- gotcha For Python 3.11 and newer, the standard library's `datetime.fromisoformat` offers highly performant ISO 8601 parsing. While `ciso8601` still aims to be faster, the performance difference may not be significant enough to warrant an external dependency for all use cases, especially if `datetime.fromisoformat` meets requirements.
Install
-
pip install ciso8601
Imports
- parse_datetime
from ciso8601 import parse_datetime
- parse_datetime_as_naive
from ciso8601 import parse_datetime_as_naive
- parse_rfc3339
from ciso8601 import parse_rfc3339
Quickstart
import ciso8601
# Parse a naive datetime string
date_str_naive = "2023-10-27T10:00:00"
dt_naive = ciso8601.parse_datetime(date_str_naive)
print(f"Naive: {dt_naive} (Type: {type(dt_naive)}) (TZ: {dt_naive.tzinfo})")
# Parse a timezone-aware datetime string
date_str_aware = "2023-10-27T10:00:00+01:00"
dt_aware = ciso8601.parse_datetime(date_str_aware)
print(f"Aware: {dt_aware} (Type: {type(dt_aware)}) (TZ: {dt_aware.tzinfo})")
# Parse as naive, even if timezone is present
date_str_aware_to_naive = "2023-10-27T10:00:00Z"
dt_forced_naive = ciso8601.parse_datetime_as_naive(date_str_aware_to_naive)
print(f"Forced Naive: {dt_forced_naive} (Type: {type(dt_forced_naive)}) (TZ: {dt_forced_naive.tzinfo})")
# Strict RFC 3339 parsing
# RFC 3339 requires a full date and time with a timezone offset or 'Z'
try:
dt_rfc3339 = ciso8601.parse_rfc3339("2023-10-27T10:00:00Z")
print(f"RFC3339: {dt_rfc3339} (TZ: {dt_rfc3339.tzinfo})")
ciso8601.parse_rfc3339("2023-10-27") # This will raise ValueError
except ValueError as e:
print(f"Error parsing non-RFC3339 string with parse_rfc3339: {e}")