I tried to write a shorter function:
def iso8601(tdelta):
ts = tdelta.total_seconds()
d = int(ts // 86400)
s = round(ts % 60, 6)
hms = int(ts // 3600 % 24), int(ts // 60 % 60), s if s % 1 != 0 else int(s)
t = ''.join([str(p[0]) + p[1] for p in zip(hms, ['H', 'M', 'S']) if p[0]])
sep = 'T' if any(hms) else ''
return 'P' + (str(d) + 'D' if d else '') + sep + (t if ts else 'T0S')
E.g.
>>> iso8601(datetime.timedelta(0, 18, 179651))
'PT18.179651S'
This may be less readable for some, but I think it's easier to take it apart and inline it in certain use cases. For example, if you're not using timedelta but already have the duration in integer seconds ts
and, say, your durations are always shorter than a day, this becomes:
hms = ts // 3600, ts // 60 % 60, ts % 60
t = ''.join([str(p[0]) + p[1] for p in zip(hms, ['H', 'M', 'S']) if p[0]])
ts_iso8601 = 'PT' + t if ts else 'PT0S'
isodate
module on PyPI can do that. You can look into its source code to see how it's implemented. – Litchiisodate.duration_isoformat(timedelta)
. Thanks. – Lassie