我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
当前回答
一个班轮。由于timedelta不提供datetime的strftime,所以将timedelta带回datetime,并使用stftime。
这不仅可以实现OP要求的格式Hours:Minutes,现在您可以利用datetime的strftime的全部格式化功能,如果您的需求更改为另一种表示形式。
import datetime
td = datetime.timedelta(hours=2, minutes=10, seconds=5)
print(td)
print(datetime.datetime.strftime(datetime.datetime.strptime(str(td), "%H:%M:%S"), "%H:%M"))
Output:
2:10:05
02:10
这也解决了时间增量被格式化为H:MM:SS而不是HH:MM:SS的字符串的烦恼,这导致了我的这个问题,以及我分享的解决方案。
其他回答
我有一个函数:
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'
如果你已经有一个timedelta obj,那么只需将obj转换为字符串。删除字符串的最后3个字符并打印。这将截断秒部分,并以小时:分钟的格式打印其余部分。
t = str(timedeltaobj)
print t[:-3]
下面是一个stringify timedelta.total_seconds()的函数。它在python2和python3中工作。
def strf_interval(seconds):
days, remainder = divmod(seconds, 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
return '{} {} {} {}'.format(
"" if int(days) == 0 else str(int(days)) + ' days',
"" if int(hours) == 0 else str(int(hours)) + ' hours',
"" if int(minutes) == 0 else str(int(minutes)) + ' mins',
"" if int(seconds) == 0 else str(int(seconds)) + ' secs'
)
示例输出:
>>> print(strf_interval(1))
1 secs
>>> print(strf_interval(100))
1 mins 40 secs
>>> print(strf_interval(1000))
16 mins 40 secs
>>> print(strf_interval(10000))
2 hours 46 mins 40 secs
>>> print(strf_interval(100000))
1 days 3 hours 46 mins 40 secs
# 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("")
我在工作中遇到过类似的加班计算输出问题。该值应该始终以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'