我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
我在格式化日期时间时遇到了麻烦。timedelta对象。
这就是我想做的: 我有一个对象列表,对象类的成员之一是显示事件持续时间的timedelta对象。我想以小时:分钟的格式显示这个持续时间。
我尝试了各种方法来做这件事,但我有困难。我目前的方法是为返回小时和分钟的对象在类中添加方法。我可以通过除以time得到小时数。秒乘以3600,四舍五入。我在得到剩余的秒并将其转换为分钟时遇到了麻烦。
顺便说一下,我使用谷歌AppEngine和Django模板来表示。
当前回答
我知道这是一个老问题,但我使用datetime.utcfromtimestamp()来解决这个问题。它接受秒数并返回一个datetime,该datetime可以像任何其他datetime一样格式化。
duration = datetime.utcfromtimestamp(end - begin)
print duration.strftime('%H:%M')
只要您停留在时间部分的合法范围内,这就应该工作,即它不会返回1234:35,因为小时<= 23。
其他回答
下面是一个通用函数,用于将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
from django.utils.translation import ngettext
def localize_timedelta(delta):
ret = []
num_years = int(delta.days / 365)
if num_years > 0:
delta -= timedelta(days=num_years * 365)
ret.append(ngettext('%d year', '%d years', num_years) % num_years)
if delta.days > 0:
ret.append(ngettext('%d day', '%d days', delta.days) % delta.days)
num_hours = int(delta.seconds / 3600)
if num_hours > 0:
delta -= timedelta(hours=num_hours)
ret.append(ngettext('%d hour', '%d hours', num_hours) % num_hours)
num_minutes = int(delta.seconds / 60)
if num_minutes > 0:
ret.append(ngettext('%d minute', '%d minutes', num_minutes) % num_minutes)
return ' '.join(ret)
这将产生:
>>> from datetime import timedelta
>>> localize_timedelta(timedelta(days=3660, minutes=500))
'10 years 10 days 8 hours 20 minutes'
def seconds_to_time_left_string(total_seconds):
s = int(total_seconds)
years = s // 31104000
if years > 1:
return '%d years' % years
s = s - (years * 31104000)
months = s // 2592000
if years == 1:
r = 'one year'
if months > 0:
r += ' and %d months' % months
return r
if months > 1:
return '%d months' % months
s = s - (months * 2592000)
days = s // 86400
if months == 1:
r = 'one month'
if days > 0:
r += ' and %d days' % days
return r
if days > 1:
return '%d days' % days
s = s - (days * 86400)
hours = s // 3600
if days == 1:
r = 'one day'
if hours > 0:
r += ' and %d hours' % hours
return r
s = s - (hours * 3600)
minutes = s // 60
seconds = s - (minutes * 60)
if hours >= 6:
return '%d hours' % hours
if hours >= 1:
r = '%d hours' % hours
if hours == 1:
r = 'one hour'
if minutes > 0:
r += ' and %d minutes' % minutes
return r
if minutes == 1:
r = 'one minute'
if seconds > 0:
r += ' and %d seconds' % seconds
return r
if minutes == 0:
return '%d seconds' % seconds
if seconds == 0:
return '%d minutes' % minutes
return '%d minutes and %d seconds' % (minutes, seconds)
for i in range(10):
print pow(8, i), seconds_to_time_left_string(pow(8, i))
Output:
1 1 seconds
8 8 seconds
64 one minute and 4 seconds
512 8 minutes and 32 seconds
4096 one hour and 8 minutes
32768 9 hours
262144 3 days
2097152 24 days
16777216 6 months
134217728 4 years
我的datetime。Timedelta对象的时间大于一天。这是一个更深层次的问题。以上所有讨论都假设时间不超过一天。timedelta实际上是一个由日、秒和微秒组成的元组。上面的讨论应该使用td。秒,因为乔做了,但如果你有天,它不包括在秒值。
我得到2个日期时间和打印天和小时之间的时间跨度。
span = currentdt - previousdt
print '%d,%d\n' % (span.days,span.seconds/3600)
我想这样做,所以写了一个简单的函数。它对我来说非常有用,而且非常通用(支持年到微秒,以及任何粒度级别,例如,你可以选择“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