我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
当前回答
在这里,我会认真考虑奥卡姆剃刀方法:
td = str(timedelta).split('.')[0]
这将返回一个没有微秒的字符串
如果要重新生成datetime。Timedelta对象,只需要这样做:
h,m,s = re.split(':', td)
new_delta = datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s))
2年了,我爱上了这门语言!
其他回答
我在工作中遇到过类似的加班计算输出问题。该值应该始终以HH:MM显示,即使它大于一天并且该值可能为负值。我结合了一些展示的解决方案,也许其他人会发现这个解决方案很有用。我意识到,如果timedelta值为负,大多数divmod方法所显示的解决方案都不能开箱即用:
def td2HHMMstr(td):
'''Convert timedelta objects to a HH:MM string with (+/-) sign'''
if td < datetime.timedelta(seconds=0):
sign='-'
td = -td
else:
sign = ''
tdhours, rem = divmod(td.total_seconds(), 3600)
tdminutes, rem = divmod(rem, 60)
tdstr = '{}{:}:{:02d}'.format(sign, int(tdhours), int(tdminutes))
return tdstr
timedelta to HH:MM
td2HHMMstr(datetime.timedelta(hours=1, minutes=45))
'1:54'
td2HHMMstr(datetime.timedelta(days=2, hours=3, minutes=2))
'51:02'
td2HHMMstr(datetime.timedelta(hours=-3, minutes=-2))
'-3:02'
td2HHMMstr(datetime.timedelta(days=-35, hours=-3, minutes=-2))
'-843:02'
我有一个函数:
def period(delta, pattern):
d = {'d': delta.days}
d['h'], rem = divmod(delta.seconds, 3600)
d['m'], d['s'] = divmod(rem, 60)
return pattern.format(**d)
例子:
>>> td = timedelta(seconds=123456789)
>>> period(td, "{d} days {h}:{m}:{s}")
'1428 days 21:33:9'
>>> period(td, "{h} hours, {m} minutes and {s} seconds, {d} days")
'21 hours, 33 minutes and 9 seconds, 1428 days'
针对这个问题的一个直接的模板过滤器。内置函数int()从不四舍五入。f - string(即f'')需要python 3.6。
@app_template_filter()
def diffTime(end, start):
diff = (end - start).total_seconds()
d = int(diff / 86400)
h = int((diff - (d * 86400)) / 3600)
m = int((diff - (d * 86400 + h * 3600)) / 60)
s = int((diff - (d * 86400 + h * 3600 + m *60)))
if d > 0:
fdiff = f'{d}d {h}h {m}m {s}s'
elif h > 0:
fdiff = f'{h}h {m}m {s}s'
elif m > 0:
fdiff = f'{m}m {s}s'
else:
fdiff = f'{s}s'
return fdiff
我想这样做,所以写了一个简单的函数。它对我来说非常有用,而且非常通用(支持年到微秒,以及任何粒度级别,例如,你可以选择“2天4小时48分钟”和“2天4小时”和“2天4.8小时”等。
def pretty_print_timedelta(t, max_components=None, max_decimal_places=2):
'''
Print a pretty string for a timedelta.
For example datetime.timedelta(days=2, seconds=17280) will be printed as '2 days, 4 hours, 48 minutes'. Setting max_components to e.g. 1 will change this to '2.2 days', where the
number of decimal points can also be set.
'''
time_scales = [timedelta(days=365), timedelta(days=1), timedelta(hours=1), timedelta(minutes=1), timedelta(seconds=1), timedelta(microseconds=1000), timedelta(microseconds=1)]
time_scale_names_dict = {timedelta(days=365): 'year',
timedelta(days=1): 'day',
timedelta(hours=1): 'hour',
timedelta(minutes=1): 'minute',
timedelta(seconds=1): 'second',
timedelta(microseconds=1000): 'millisecond',
timedelta(microseconds=1): 'microsecond'}
count = 0
txt = ''
first = True
for scale in time_scales:
if t >= scale:
count += 1
if count == max_components:
n = t / scale
else:
n = int(t / scale)
t -= n*scale
n_txt = str(round(n, max_decimal_places))
if n_txt[-2:]=='.0': n_txt = n_txt[:-2]
txt += '{}{} {}{}'.format('' if first else ', ', n_txt, time_scale_names_dict[scale], 's' if n>1 else '', )
if first:
first = False
if len(txt) == 0:
txt = 'none'
return txt
# Format seconds to days, hours, minutes and seconds string
def ptime(seconds):
if(seconds >= 86400):
d = seconds // 86400 # // floor division
return (f"{round(d)}d") + ptime(seconds - d * 86400)
else:
if(seconds >= 3600):
h = seconds // 3600
return (f"{round(h)}h") + ptime(seconds - h * 3600)
else:
if(seconds >= 60):
m = seconds // 60
return(f"{round(m)}m" + ptime(seconds - m * 60))
else:
if (seconds > 0):
return(f"{round(seconds)}s")
else:
return("")