我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
当前回答
如果您的包中碰巧有IPython(您应该),那么它(到目前为止)有一个非常好的持续时间格式器(以浮点秒为单位)。它被用于许多地方,例如%%时间单元格魔法。我喜欢它在短时间内产生的格式:
>>> from IPython.core.magics.execution import _format_time
>>>
>>> for v in range(-9, 10, 2):
... dt = 1.25 * 10**v
... print(_format_time(dt))
1.25 ns
125 ns
12.5 µs
1.25 ms
125 ms
12.5 s
20min 50s
1d 10h 43min 20s
144d 16h 13min 20s
14467d 14h 13min 20s
其他回答
我知道这是一个老问题,但我使用datetime.utcfromtimestamp()来解决这个问题。它接受秒数并返回一个datetime,该datetime可以像任何其他datetime一样格式化。
duration = datetime.utcfromtimestamp(end - begin)
print duration.strftime('%H:%M')
只要您停留在时间部分的合法范围内,这就应该工作,即它不会返回1234:35,因为小时<= 23。
提问者想要一个比典型的更好的格式:
>>> import datetime
>>> datetime.timedelta(seconds=41000)
datetime.timedelta(0, 41000)
>>> str(datetime.timedelta(seconds=41000))
'11:23:20'
>>> str(datetime.timedelta(seconds=4102.33))
'1:08:22.330000'
>>> str(datetime.timedelta(seconds=413302.33))
'4 days, 18:48:22.330000'
所以,实际上有两种格式,一种是天数为0,它被省略了,另一种是文本“n天,h:m:s”。但是,秒可能有分数,打印输出中没有前导0,所以列很乱。
如果你喜欢,下面是我的日常工作:
def printNiceTimeDelta(stime, etime):
delay = datetime.timedelta(seconds=(etime - stime))
if (delay.days > 0):
out = str(delay).replace(" days, ", ":")
else:
out = "0:" + str(delay)
outAr = out.split(':')
outAr = ["%02d" % (int(float(x))) for x in outAr]
out = ":".join(outAr)
return out
返回dd:hh:mm:ss格式的输出:
00:00:00:15
00:00:00:19
02:01:31:40
02:01:32:22
我确实想过在上面加上年份,但这是留给读者的练习,因为超过1年的输出是安全的:
>>> str(datetime.timedelta(seconds=99999999))
'1157 days, 9:46:39'
如您所知,您可以通过访问.seconds属性从timedelta对象中获得total_seconds。
Python提供了内置函数divmod(),它允许:
s = 13420
hours, remainder = divmod(s, 3600)
minutes, seconds = divmod(remainder, 60)
print('{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds)))
# result: 03:43:40
或者你可以结合使用模和减法来转换小时和余数:
# arbitrary number of seconds
s = 13420
# hours
hours = s // 3600
# remaining seconds
s = s - (hours * 3600)
# minutes
minutes = s // 60
# remaining seconds
seconds = s - (minutes * 60)
# total time
print('{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds)))
# result: 03:43:40
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime('%H:%M'))
我接着MarredCheese的回答,加上了年、月、毫秒和微秒
除秒外,所有数字都被格式化为整数,因此秒的分数可以自定义。
@kfmfe04要求几分之一秒,所以我发布了这个解决方案
大体上有一些例子。
from string import Formatter
from datetime import timedelta
def strfdelta(tdelta, fmt='{D:02}d {H:02}h {M:02}m {S:02.0f}s', inputtype='timedelta'):
"""Convert a datetime.timedelta object or a regular number to a custom-
formatted string, just like the stftime() method does for datetime.datetime
objects.
The fmt argument allows custom formatting to be specified. Fields can
include seconds, minutes, hours, days, and weeks. Each field is optional.
Some examples:
'{D:02}d {H:02}h {M:02}m {S:02.0f}s' --> '05d 08h 04m 02s' (default)
'{W}w {D}d {H}:{M:02}:{S:02.0f}' --> '4w 5d 8:04:02'
'{D:2}d {H:2}:{M:02}:{S:02.0f}' --> ' 5d 8:04:02'
'{H}h {S:.0f}s' --> '72h 800s'
The inputtype argument allows tdelta to be a regular number instead of the
default, which is a datetime.timedelta object. Valid inputtype strings:
's', 'seconds',
'm', 'minutes',
'h', 'hours',
'd', 'days',
'w', 'weeks'
"""
# Convert tdelta to integer seconds.
if inputtype == 'timedelta':
remainder = tdelta.total_seconds()
elif inputtype in ['s', 'seconds']:
remainder = float(tdelta)
elif inputtype in ['m', 'minutes']:
remainder = float(tdelta)*60
elif inputtype in ['h', 'hours']:
remainder = float(tdelta)*3600
elif inputtype in ['d', 'days']:
remainder = float(tdelta)*86400
elif inputtype in ['w', 'weeks']:
remainder = float(tdelta)*604800
f = Formatter()
desired_fields = [field_tuple[1] for field_tuple in f.parse(fmt)]
possible_fields = ('Y','m','W', 'D', 'H', 'M', 'S', 'mS', 'µS')
constants = {'Y':86400*365.24,'m': 86400*30.44 ,'W': 604800, 'D': 86400, 'H': 3600, 'M': 60, 'S': 1, 'mS': 1/pow(10,3) , 'µS':1/pow(10,6)}
values = {}
for field in possible_fields:
if field in desired_fields and field in constants:
Quotient, remainder = divmod(remainder, constants[field])
values[field] = int(Quotient) if field != 'S' else Quotient + remainder
return f.format(fmt, **values)
if __name__ == "__main__":
td = timedelta(days=717, hours=3, minutes=5, seconds=8, microseconds=3549)
print(strfdelta(td,'{Y} years {m} months {W} weeks {D} days {H:02}:{M:02}:{S:02}'))
print(strfdelta(td,'{m} months {W} weeks {D} days {H:02}:{M:02}:{S:02.4f}'))
td = timedelta( seconds=8, microseconds=8549)
print(strfdelta(td,'{S} seconds {mS} milliseconds {µS} microseconds'))
print(strfdelta(td,'{S:.0f} seconds {mS} milliseconds {µS} microseconds'))
print(strfdelta(pow(10,7),inputtype='s'))
输出:
1 years 11 months 2 weeks 3 days 01:09:56.00354900211096
23 months 2 weeks 3 days 00:12:20.0035
8.008549 seconds 8 milliseconds 549 microseconds
8 seconds 8 milliseconds 549 microseconds
115d 17h 46m 40s