在Python中将datetime.timedelta转换为ISO 8601 duration?
给定datetime.timedelta,如何将其转换为ISO 8601 duration格式的字符串 前, 这是project(Apache许可证2.0)中的一个函数,可以进行转换:在Python中将datetime.timedelta转换为ISO 8601 duration?,python,iso8601,timedelta,python-datetime,Python,Iso8601,Timedelta,Python Datetime,给定datetime.timedelta,如何将其转换为ISO 8601 duration格式的字符串 前, 这是project(Apache许可证2.0)中的一个函数,可以进行转换: def iso8601(value): # split seconds to larger units seconds = value.total_seconds() minutes, seconds = divmod(seconds, 60) hours, minutes = d
def iso8601(value):
# split seconds to larger units
seconds = value.total_seconds()
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
days, hours = divmod(hours, 24)
days, hours, minutes = map(int, (days, hours, minutes))
seconds = round(seconds, 6)
## build date
date = ''
if days:
date = '%sD' % days
## build time
time = u'T'
# hours
bigger_exists = date or hours
if bigger_exists:
time += '{:02}H'.format(hours)
# minutes
bigger_exists = bigger_exists or minutes
if bigger_exists:
time += '{:02}M'.format(minutes)
# seconds
if seconds.is_integer():
seconds = '{:02}'.format(int(seconds))
else:
# 9 chars long w/leading 0, 6 digits after decimal
seconds = '%09.6f' % seconds
# remove trailing zeros
seconds = seconds.rstrip('0')
time += '{}S'.format(seconds)
return u'P' + date + time
例如
虽然包含用于datetime
或date
对象的ISO 8601表示法的实现,但它目前(Python 3.7)不支持timedelta
对象的ISO 8601表示法。但是,具有以ISO 8601表示法生成持续时间字符串的功能:
In [15]: import isodate, datetime
In [16]: print(isodate.duration_isoformat(datetime.datetime.now() - datetime.datetime(1985, 8, 13, 15)))
P12148DT4H20M39.47017S
这意味着12148天4小时20分钟39.47017秒。我试图写一个更短的函数:
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')
例如
对于某些人来说,这可能不太可读,但我认为在某些用例中更容易将其拆分并内联。例如,如果您没有使用timedelta,但已经有整数秒的持续时间ts
,并且您的持续时间总是短于一天,则这将变为:
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'
参见()ISO8601可能包括时区偏移
import datetime
date=datetime.datetime.now().astimezone().isoformat()
2020-03-20T14:32:16.458361+13:00
date.isoformat()
我能做到。您可以查看它是如何实现的。@Carsten它通过isodate:
isodate.duration\u isoformat(timedelta)
工作得很好。谢谢。最好使用:isodate.duration\u isoformat(timedelta)我个人觉得你的代码很难读。更长的变量名将是一个很大的改进。我完全同意,甚至在答案中提到这一点。函数(第一块)不是我在生产过程中会使用的东西,它更多的是一个简洁的练习,导致了子集三行解决方案(第三块),在某些情况下可以容忍(或容易澄清)。是的,但是不要忘记,很多人只是盲目地复制和粘贴答案,所以很多初学者都会采用这种编码方式。这就是为什么我个人尽可能地坚持产品质量代码。
>>> iso8601(datetime.timedelta(0, 18, 179651))
'PT18.179651S'
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'
import datetime
date=datetime.datetime.now().astimezone().isoformat()
2020-03-20T14:32:16.458361+13:00
date.isoformat()