Skip to content

Instantly share code, notes, and snippets.

@pganssle
Created October 21, 2017 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pganssle/930756cc93f7d888ab63363eb33d5fe5 to your computer and use it in GitHub Desktop.
Save pganssle/930756cc93f7d888ab63363eb33d5fe5 to your computer and use it in GitHub Desktop.
from datetime import datetime, timedelta, timezone
def strptime_z(dt_str, fmt_str):
# Hard-coded so this demo works, not an actual proposed strptime_z
tzi = None
if fmt_str.endswith('%:z'):
tz_str = dt_str[-6:]
h, m = map(int, tz_str.split(':'))
tzi = timezone(offset=timedelta(hours=h, minutes=m))
fmt_str = fmt_str[:-len('%:z')]
dt_str = dt_str[:-6]
return datetime.strptime(dt_str, fmt_str).replace(tzinfo=tzi)
def isoparse(dt_str, sep='T'):
base_fmt = "%Y-%m-%d"
len_str = len(dt_str)
if len_str > 10:
base_fmt += sep
if len_str == 10:
tail = ''
elif len_str == 13:
tail = '%H' # hours, no tzinfo
elif len_str == 16:
tail = '%H:%M' # minutes, no tzinfo
elif len_str == 19:
if dt_str[-6] in '-+':
tail = '%H%:z' # hours, with tzinfo
else:
tail = '%H:%M:%S' # seconds, no tzinfo
elif len_str == 22:
tail = '%H:%M%:z' # minutes, with tzinfo
elif len_str in {23, 26}:
tail = '%H:%M:%S.%f' # milliseconds/microseconds, no tzinfo
elif len_str== 25:
tail = '%H:%M:%S%:z' # seconds, with tzinfo
elif len_str in {29, 32}:
tail = '%H:%M:%S.%f%:z' # milliseconds/microseconds, with tzinfo
else:
raise ValueError('Invalid isoformat string')
return strptime_z(dt_str, base_fmt + tail)
if __name__ == "__main__":
dt = datetime(2017, 4, 1, 14, 24, 32, tzinfo=tz.gettz('US/Eastern'))
timespecs = ['hours', 'minutes',
'seconds', 'milliseconds', 'microseconds']
tzinfos = [timezone(timedelta(hours=-4)), None]
seps = ('T', ' ')
outputs = []
for tzi in tzinfos:
for ii, timespec in enumerate(timespecs):
for sep in seps:
dt_tz = dt.replace(tzinfo=tzi)
dt_str = dt_tz.isoformat(timespec=timespec, sep=sep)
dt_comp = dt_tz
if ii < timespecs.index('milliseconds'):
dt_comp = dt_comp.replace(microsecond=0)
if ii < timespecs.index('seconds'):
dt_comp = dt_comp.replace(second=0)
if ii < timespecs.index('minutes'):
dt_comp = dt_comp.replace(minute=0)
assert dt_comp == isoparse(dt_str, sep=sep)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment