格式化timedelta对象
我有两个 datetime
对象。我需要计算它们之间的 timedelta
,然后以特定的格式显示结果。
Alpha_TimeObj = datetime.datetime(int(AlphaTime.strftime('%Y')), int(AlphaTime.strftime('%m')), int(AlphaTime.strftime('%d')), int(AlphaTime.strftime('%H')), int(AlphaTime.strftime('%M')), int(AlphaTime.strftime('%S')))
Beta_TimeObj = datetime.datetime(int(BetaTime.strftime('%Y')), int(BetaTime.strftime('%m')), int(BetaTime.strftime('%d')), int(BetaTime.strftime('%H')), int(BetaTime.strftime('%M')), int(BetaTime.strftime('%S')))
Turnaround_TimeObj = Beta_TimeObj - Alpha_TimeObj
比如这个 Turnaround_TimeObj
的时间差是 "2 days, 22:13:45"。我想把输出格式化一下,但我不知道怎么做。
print Turnaround_TimeObj.strftime('%H hrs %M mins %S secs')
这个方法不行。
我知道一种方法是把它转换成秒,然后用除法和取余的方法来得到想要的格式。
就像这样:
totalSeconds = Turnaround_TimeObj.seconds
hours, remainder = divmod(totalSeconds, 3600)
minutes, seconds = divmod(remainder, 60)
print '%s:%s:%s' % (hours, minutes, seconds)
但是我在想,能不能用像 strftime
这样的日期时间函数在一行代码里完成这个操作。
其实,把它转换成秒也不行。如果我用下面的方式把时间差 "1 day, 3:42:54" 转换成秒:
totalSeconds = Turnaround_TimeObj.seconds
那么 totalSeconds
的值显示为 13374,而不是 99774。也就是说,它忽略了 "day" 的值。
7 个回答
在Python 2.7或更新的版本中,你可以使用total_seconds这个方法:
import datetime as dt
turnaround = dt.timedelta(days = 1, hours = 3, minutes = 42, seconds = 54)
total_seconds = int(turnaround.total_seconds())
hours, remainder = divmod(total_seconds,60*60)
minutes, seconds = divmod(remainder,60)
print('{} hrs {} mins {} secs'.format(hours,minutes,seconds))
这样会得到
27 hrs 42 mins 54 secs
在Python 2.6或更早的版本中,你需要自己计算total_seconds
:
total_seconds = turnaround.seconds + turnaround.days*24*60*60
(如果你想要更通用的公式,包括微秒,可以查看上面的链接)。
这是对Shawn Chin的回答的一个小改动,同时也解决了mpouncett提出的一个后续问题。这个改动的主要目的是在小时、分钟和秒前面加上零,这样可以确保这三个部分都是两位数(这和strftime中对这些字段的规定更一致):
from string import Template
class DeltaTemplate(Template):
delimiter = "%"
def strfdelta(tdelta, fmt):
d = {"D": tdelta.days}
hours, rem = divmod(tdelta.seconds, 3600)
minutes, seconds = divmod(rem, 60)
d["H"] = '{:02d}'.format(hours)
d["M"] = '{:02d}'.format(minutes)
d["S"] = '{:02d}'.format(seconds)
t = DeltaTemplate(fmt)
return t.substitute(**d)
下面是一些示例值的测试:
from datetime import timedelta
for seconds in [0, 1, 59, 60, 61, 3599, 3600, 3601]:
print strfdelta(timedelta(0, seconds), '%H:%M:%S')
这是输出结果:
00:00:00
00:00:01
00:00:59
00:01:00
00:01:01
00:59:59
01:00:00
01:00:01
我在想,能不能用像
strftime
这样的日期时间函数,把它写成一行代码。
根据我的了解,timedelta
里没有直接的方法可以做到这一点。如果你经常需要这样做,可以自己写一个函数,比如:
def strfdelta(tdelta, fmt):
d = {"days": tdelta.days}
d["hours"], rem = divmod(tdelta.seconds, 3600)
d["minutes"], d["seconds"] = divmod(rem, 60)
return fmt.format(**d)
用法:
>>> print strfdelta(delta_obj, "{days} days {hours}:{minutes}:{seconds}")
1 days 20:18:12
>>> print strfdelta(delta_obj, "{hours} hours and {minutes} to go")
20 hours and 18 to go
如果你想用一种更接近 strftime
的字符串格式,我们可以使用 string.Template
:
from string import Template
class DeltaTemplate(Template):
delimiter = "%"
def strfdelta(tdelta, fmt):
d = {"D": tdelta.days}
d["H"], rem = divmod(tdelta.seconds, 3600)
d["M"], d["S"] = divmod(rem, 60)
t = DeltaTemplate(fmt)
return t.substitute(**d)
用法:
>>> print strfdelta(delta_obj, "%D days %H:%M:%S")
1 days 20:18:12
>>> print strfdelta(delta_obj, "%H hours and %M to go")
20 hours and 18 to go
这里的
totalSeconds
值显示为 13374,而不是 99774。也就是说,它忽略了“天”的值。
在上面的例子中,你可以用 timedelta.days
来获取“天”的值。
另外,从 Python 2.7 开始,timedelta
有一个 total_seconds() 方法,可以返回这个时间段内的总秒数。