- Add support for aarch64 wheels. Thank you @bbayles!
- Add wheels for PyPy 3.10
- Added Python 3.12 wheels
- Added Python 3.11 support
- Fix the build for PyPy2 (#116)
- Added missing
fromutc
implementation forFixedOffset
(#113). Thanks @davidkraljic - Removed improper ability to call
FixedOffset
'sdst
,tzname
andutcoffset
without arguments - Fixed:
datetime.tzname
returns astr
in Python 2.7, not aunicode
- Change
METH_VARARGS
toMETH_O
, enhancing performance. (#130) - Added support for ISO week dates, (#139)
- Added support for ordinal dates, (#140)
- Added Python 3.9 support
- Switched to using a C implementation of
timezone
objects.- Much faster parse times for timestamps with timezone information
- ~2.5x faster on Python 2.7, ~10% faster on Python 3.9
- Thanks to
pendulum
and @sdispater for the code. - Python 2.7 users no longer need to install
pytz
dependency 😃
- Much faster parse times for timestamps with timezone information
- Added caching of tzinfo objects
- Parsing is ~1.1x faster for subsequent timestamps that have the same time zone offset.
- Caching can be disabled at compile time by setting the
CISO8601_CACHING_ENABLED=0
environment variable
- Fixed a memory leak in the case where an invalid timestamp had a non-UTC timezone and extra characters
- Fixed a problem where non-ASCII characters would give bad error messages (#84). Thanks @olliemath.
- Fixed a problem where
ciso8601.__version__
was not working (#80). Thanks @ianhoffman. - Added Python 3.8 support (#83)
- Added benchmarking scripts (#55)
- Fixed a problem where builds on Windows were not working (#76). Thanks @alexandrul and @gillesdouaire, and sorry.
- Added Mypy/PEP 484 typing information (#68, Thanks @NickG123).
- Added a new function:
parse_rfc3339
, which strictly parses RFC 3339 (#70). - No longer accept mixed "basic" and "extended" format timestamps (#73).
- e.g.,
20140203T23:35:27
and2014-02-03T233527
are not valid in ISO 8601, but were not raisingValueError
. - Attempting to parse such timestamps now raises
ValueError
- e.g.,
- Fixed some memory leaks introduced in 2.0.0 (#51)
Version 2.0.0 was a major rewrite of ciso8601
.
Version 1.x.x had a problem with error handling in the case of invalid timestamps.
In 1.x.x, parse_datetime:
- All valid datetime strings within the supported subset of ISO 8601 would result in the correct Python datetime (this was good)
- Some invalid timestamps will return
None
and others might get truncated and return an incorrect Python datetime (this was bad)
A developer with a given timestamp string, could not predict a priori what ciso8601
is going to return without looking at the code.
Fundamentally, this is the problem that version 2 addressed.
Fundamentally, parse_datetime(dt: String): datetime
was rewritten so that it takes a string and either:
- Returns a properly parsed Python datetime, if and only if that entire string conforms to the supported subset of ISO 8601
- Raises an
ValueError
with a description of the reason why the string doesn't conform to the supported subset of ISO 8601
- Version 2 now raises
ValueError
when a timestamp does not conform to the supported subset of ISO 8601- This includes trailing characters in the timestamp
- No longer accepts single character "day" values
- See migration guide below for more examples
parse_datetime_unaware
was renamed toparse_datetime_as_naive
(See "Migration Guide" below for reasons)
- Attempting to parse a timestamp with time zone information without having pytz installed raises
ImportError
(Only affects Python 2.7). Fixes #19 - Added support for the special case of midnight (24:00:00) that is valid in ISO 8601. Fixes #41
- Fixed bug where "20140200" would not fail, but produce 2014-02-01. Fixes #42
Places where you were checking for a return of None
from ciso8601:
timestamp = "2018-01-01T00:00:00+05:00"
dt = parse_datetime(timestamp)
if dt is None:
raise ValueError(f"Could not parse {timestamp}")
You should change to now expect ValueError
to be thrown:
timestamp = "2018-01-01T00:00:00+05:00"
dt = parse_datetime(timestamp)
The rules with respect to what ciso8601 will consider a conforming ISO 8601 string have been tightened.
Now a timestamp will parse if and only if the timestamp is 100% conforming to the supported subset of the ISO 8601 specification.
# trailing separator
"2014-"
"2014-01-"
"2014-01-01T"
"2014-01-01T00:"
"2014-01-01T00:00:"
"2014-01-01T00:00:00-"
"2014-01-01T00:00:00-00:"
# Mix of no-separator and separator
"201401-02"
"2014-0102"
"2014-01-02T00:0000"
"2014-01-02T0000:00"
"2014-01-02T01:23:45Zabcdefghij" # Trailing characters
"2014-01-1" # Single digit day
"2014-01-01T00:00:00-0:04" # Single digit tzhour
"2014-01-01T00:00:00-00:4" # Single digit tzminute
These should have been considered bugs in ciso8601 1.x.x, but it may be the case that your code was relying on the previously lax parsing rules.
parse_datetime_unaware
existed for the case where your input timestamp had time zone information, but you wanted to ignore the time zone information and therefore could save some cycles by not creating the underlying tzinfo
object.
It has been renamed to parse_datetime_as_naive
for 2 reasons:
- Developers were assuming that
parse_datetime_unaware
was the function to use for parsing naive timestamps, when really it is for parsing timestamps with time zone information as naive datetimes.parse_datetime
handles parsing both timestamps with and without time zone information and should be used for all parsing, unless you actually need this use case. See additional description in the README for a more detailed description of this use case. - Python refers to datetimes without time zone information as
naive
, notunaware
Before switching all instances of parse_datetime_unaware
, make sure to ask yourself whether you actually intended to use parse_datetime_unaware
.
- If you meant to parse naive timestamps as naive datetimes, use
parse_datetime
instead. - If you actually meant to parse timestamps with time zone information as naive datetimes, use
parse_datetime_as_naive
instead.
Input with TZ Info | Input without TZ Info | |
---|---|---|
parse_datetime() output |
tz aware datetime | tz naive datetime |
parse_datetime_as_naive() output |
tz naive datetime | tz naive datetime |