Python has only limited support for parsing ISO 8601 timestamps. For strptime
you need to know exactly what format it is in. As a complication the stringification of a datetime
is an ISO 8601 timestamp, with space as a separator and 6 digit fraction:
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 555555))
# '2016-07-22 09:25:59.555555'
but if the fraction is 0, no fractional part is output
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 0))
# '2016-07-22 09:25:59'
But these 2 forms need a different format for strptime
. Furthermore, strptime' does not support at all parsing minute timezones that have a
:in it, thus
2016-07-22 09:25:59+0300can be parsed, but the standard format
2016-07-22 09:25:59+03:00` cannot.
There is a single-file library called iso8601
which properly parses ISO 8601 timestamps and only them.
It supports fractions and timezones, and the T
separator all with a single function:
import iso8601
iso8601.parse_date('2016-07-22 09:25:59')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22 09:25:59+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<FixedOffset '+03:00' ...>)
iso8601.parse_date('2016-07-22 09:25:59Z')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22T09:25:59.000111+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, 111, tzinfo=<FixedOffset '+03:00' ...>)
If no timezone is set, iso8601.parse_date
defaults to UTC. The default zone can be changed with default_zone
keyword argument. Notably, if this is None
instead of the default, then those timestamps that do not have an explicit timezone are returned as naive datetimes instead:
iso8601.parse_date('2016-07-22T09:25:59', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59)
iso8601.parse_date('2016-07-22T09:25:59Z', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)