我是一个Python新手(2周),我在格式化datetime.timedelta
对象时遇到了麻烦.
这是我正在尝试做的事情:我有一个对象列表,该对象类的一个成员是一个timedelta对象,显示事件的持续时间.我希望以小时:分钟的格式显示该持续时间.
我已经尝试了各种方法来做到这一点,我遇到了困难.我目前的方法是为我的对象添加方法,返回小时和分钟.我可以通过将timedelta.seconds除以3600并将其四舍五入来获得小时数.我无法获得余数秒并将其转换为分钟.
顺便说一句,我正在使用Google AppEngine
它Django Templates
进行演示.
如果有人可以帮助或知道更好的解决方法,我会非常高兴.
谢谢,
您可以使用str()将timedelta转换为字符串.这是一个例子:
import datetime start = datetime.datetime(2009,2,10,14,00) end = datetime.datetime(2009,2,10,16,00) delta = end-start print(str(delta)) # prints 2:00:00
如您所知,您可以通过访问.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
>>> str(datetime.timedelta(hours=10.56)) 10:33:36 >>> td = datetime.timedelta(hours=10.505) # any timedelta object >>> ':'.join(str(td).split(':')[:2]) 10:30
将timedelta
对象传递给str()
函数会调用与我们只需键入时相同的格式代码print td
.由于您不需要秒数,我们可以用冒号(3个部分)拆分字符串,然后将它与仅前两个部分放回原处.
def td_format(td_object): seconds = int(td_object.total_seconds()) periods = [ ('year', 60*60*24*365), ('month', 60*60*24*30), ('day', 60*60*24), ('hour', 60*60), ('minute', 60), ('second', 1) ] strings=[] for period_name, period_seconds in periods: if seconds > period_seconds: period_value , seconds = divmod(seconds, period_seconds) has_s = 's' if period_value > 1 else '' strings.append("%s %s%s" % (period_value, period_name, has_s)) return ", ".join(strings)
他已经有了一个timedelta对象,为什么不使用它的内置方法total_seconds()将其转换为秒,然后使用divmod()来获取小时和分钟?
hours, remainder = divmod(myTimeDelta.total_seconds(), 3600) minutes, seconds = divmod(remainder, 60) # Formatted only for hours and minutes as requested print '%s:%s' % (hours, minutes)
无论时间增量是否有几天或几年,这都有效.
我个人使用这个humanize
库:
>>> import datetime >>> humanize.naturalday(datetime.datetime.now()) 'today' >>> humanize.naturalday(datetime.datetime.now() - datetime.timedelta(days=1)) 'yesterday' >>> humanize.naturalday(datetime.date(2007, 6, 5)) 'Jun 05' >>> humanize.naturaldate(datetime.date(2007, 6, 5)) 'Jun 05 2007' >>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=1)) 'a second ago' >>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600)) 'an hour ago'
当然,它不会给你确切地你要找的人(这是确实的答案str(timeA - timeB)
,但我发现,一旦你超越了几个小时,显示变得不可读很快.humanize
对那些更大价值的支持人类可读,也很好地本地化.
它的灵感来自Django的contrib.humanize
模块,显然,因为你使用Django,你应该使用它.
这是一个通用函数,用于将timedelta
对象或常规数字(以秒或分钟等形式)转换为格式良好的字符串.我在一个重复的问题上采用了mpounsett的精彩答案,使其更加灵活,提高了可读性并增加了文档.
你会发现这是迄今为止最灵活的答案,因为它允许你:
即时自定义字符串格式,而不是硬编码.
留出一定的时间间隔没有问题(见下面的例子).
功能:
from string import Formatter from datetime import timedelta def strfdelta(tdelta, fmt='{D:02}d {H:02}h {M:02}m {S:02}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}s' --> '05d 08h 04m 02s' (default) '{W}w {D}d {H}:{M:02}:{S:02}' --> '4w 5d 8:04:02' '{D:2}d {H:2}:{M:02}:{S:02}' --> ' 5d 8:04:02' '{H}h {S}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 = int(tdelta.total_seconds()) elif inputtype in ['s', 'seconds']: remainder = int(tdelta) elif inputtype in ['m', 'minutes']: remainder = int(tdelta)*60 elif inputtype in ['h', 'hours']: remainder = int(tdelta)*3600 elif inputtype in ['d', 'days']: remainder = int(tdelta)*86400 elif inputtype in ['w', 'weeks']: remainder = int(tdelta)*604800 f = Formatter() desired_fields = [field_tuple[1] for field_tuple in f.parse(fmt)] possible_fields = ('W', 'D', 'H', 'M', 'S') constants = {'W': 604800, 'D': 86400, 'H': 3600, 'M': 60, 'S': 1} values = {} for field in possible_fields: if field in desired_fields and field in constants: values[field], remainder = divmod(remainder, constants[field]) return f.format(fmt, **values)
演示:
>>> td = timedelta(days=2, hours=3, minutes=5, seconds=8, microseconds=340) >>> print strfdelta(td) 02d 03h 05m 08s >>> print strfdelta(td, '{D}d {H}:{M:02}:{S:02}') 2d 3:05:08 >>> print strfdelta(td, '{D:2}d {H:2}:{M:02}:{S:02}') 2d 3:05:08 >>> print strfdelta(td, '{H}h {S}s') 51h 308s >>> print strfdelta(12304, inputtype='s') 00d 03h 25m 04s >>> print strfdelta(620, '{H}:{M:02}', 'm') 10:20 >>> print strfdelta(49, '{D}d {H}h', 'h') 2d 1h
我知道这是一个陈旧的问题,但我用datetime.utcfromtimestamp()
它.它需要秒数并返回一个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".但是,秒可能有分数,打印输出中没有前导零,所以列很乱.
如果您喜欢,这是我的常规:
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'
我的datetime.timedelta
物品超过了一天.所以这是另一个问题.上面的所有讨论都假设不到一天.A timedelta
实际上是天,秒和微秒的元组.上面的讨论应该td.seconds
像乔一样使用,但是如果你有几天它不包括在秒值中.
我在2个日期时间和打印日期和时间之间得到了一段时间.
span = currentdt - previousdt print '%d,%d\n' % (span.days,span.seconds/3600)
我会认真考虑奥卡姆的剃刀方法:
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年了,我喜欢这门语言!
按照Joe上面的示例值,我将使用模数算术运算符,因此:
td = datetime.timedelta(hours=10.56) td_str = "%d:%d" % (td.seconds/3600, td.seconds%3600/60)
请注意,默认情况下,Python中的整数除法向下舍入; 如果您想更明确,请根据需要使用math.floor()或math.ceil().
我使用humanfriendly
python库来做到这一点,它工作得很好。
import humanfriendly from datetime import timedelta delta = timedelta(seconds = 321) humanfriendly.format_timespan(delta) '5 minutes and 21 seconds'
可在https://pypi.org/project/humanfriendly/