Skip to content

Instantly share code, notes, and snippets.

@bruno-rino
Last active October 10, 2017 07:57
Show Gist options
  • Save bruno-rino/e2eb03c45d00965a32650769ea2710a4 to your computer and use it in GitHub Desktop.
Save bruno-rino/e2eb03c45d00965a32650769ea2710a4 to your computer and use it in GitHub Desktop.
Convert a ISO 8601 formatted datetime string to a python datetime. Supports basic and extended ISO 8601 formatting.
import re
from datetime import datetime, timedelta
from decimal import Decimal
def datetime_from_iso(text):
'''
Convert a ISO 8601 formatted datetime string to a python datetime
NOTE: this function is intentionally *not* timezone-aware; providing timezone information beyond 'Z' will fail.
NOTE: the parsing is sligthly too permissive; you can mix and match basic and extended ISO 8601 formatting (could be solved by using two regexes instead of one).
'''
m = re.match(r'(?P<year>\d{4})-?(?P<month>\d{2})-?(?P<day>\d{2})(T(?P<hours>\d{2})(:?(?P<minutes>\d{2})(:?(?P<seconds>\d{2}))?)?([,.](?P<fractional>\d+))?Z?)?', text)
# only keep fields that are present in the input text
data = {k: int(v) for k, v in m.groupdict().items() if v is not None}
# handle fractional time part
if 'fractional' in data:
if 'seconds' in data:
# fractional seconds
data['microseconds'] = int(str(data['fractional']).ljust(6, '0'))
elif 'minutes' in data:
# fractional minutes
value = Decimal('0.' + str(data['fractional'])) * 60 # minutes to seconds
data['seconds'] = int(value)
if value != int(value):
data['microseconds'] = int((value - int(value))*10**6)
else:
# fractional hours
value = Decimal('0.' + str(data['fractional'])) * 60 # hours to minutes
data['minutes'] = int(value)
if value != int(value):
value = (value - int(value)) * 60 # minutes to seconds
data['seconds'] = int(value)
if value != int(value):
data['microseconds'] = int((value - int(value))*10**6)
return datetime(
data.get('year', 0),
data.get('month', 0),
data.get('day', 0),
data.get('hours', 0),
data.get('minutes', 0),
data.get('seconds', 0),
data.get('microseconds', 0),
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment