如何在使用Python减去两个UNIX时间戳时产生可读的差异?

这个问题类似于用Python减去date的问题 ,但不完全相同。 我不处理string,我必须弄清楚两个时代的时间戳之间的差异,并以可读的格式产生差异。

例如:

32 Seconds 17 Minutes 22.3 Hours 1.25 Days 3.5 Weeks 2 Months 4.25 Years 

或者,我想expression这样的区别:

 4 years, 6 months, 3 weeks, 4 days, 6 hours 21 minutes and 15 seconds 

我不认为我可以使用strptime ,因为我正在处理两个时代的差异。 我可以写些东西来做到这一点,但我确信已经写了一些我可以使用的东西。

什么模块将是适当的? 我只是错过了一些time ? 我的Python入门只是真的开始,如果这确实是一个重复的,因为我没有find要search的东西。

附录

为了准确,我真的最关心今年的日历。

你可以使用精彩的dateutil模块及其相关的类:

 import datetime import dateutil.relativedelta dt1 = datetime.datetime.fromtimestamp(123456789) # 1973-11-29 22:33:09 dt2 = datetime.datetime.fromtimestamp(234567890) # 1977-06-07 23:44:50 rd = dateutil.relativedelta.relativedelta (dt2, dt1) print "%d years, %d months, %d days, %d hours, %d minutes and %d seconds" % (rd.years, rd.months, rd.days, rd.hours, rd.minutes, rd.seconds) # 3 years, 6 months, 9 days, 1 hours, 11 minutes and 41 seconds 

这不算数周,但这不应该太难添加。

对Schnouki的解决scheme有一点改进,只有一行列表理解。 在多个实体的情况下也显示复数(如小时)

导入relativedelta

 >>> from dateutil.relativedelta import relativedelta 

一个lambda函数

 >>> attrs = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'] >>> human_readable = lambda delta: ['%d %s' % (getattr(delta, attr), getattr(delta, attr) > 1 and attr or attr[:-1]) ... for attr in attrs if getattr(delta, attr)] 

用法示例:

 >>> human_readable(relativedelta(minutes=125)) ['2 hours', '5 minutes'] >>> human_readable(relativedelta(hours=(24 * 365) + 1)) ['365 days', '1 hour'] 

今天早些时候我也遇到了同样的问题,我在标准库中找不到任何可以使用的东西,所以这就是我写的:

humanize_time.py

  #!/usr/bin/env python INTERVALS = [1, 60, 3600, 86400, 604800, 2419200, 29030400] NAMES = [('second', 'seconds'), ('minute', 'minutes'), ('hour', 'hours'), ('day', 'days'), ('week', 'weeks'), ('month', 'months'), ('year', 'years')] def humanize_time(amount, units): """ Divide `amount` in time periods. Useful for making time intervals more human readable. >>> humanize_time(173, 'hours') [(1, 'week'), (5, 'hours')] >>> humanize_time(17313, 'seconds') [(4, 'hours'), (48, 'minutes'), (33, 'seconds')] >>> humanize_time(90, 'weeks') [(1, 'year'), (10, 'months'), (2, 'weeks')] >>> humanize_time(42, 'months') [(3, 'years'), (6, 'months')] >>> humanize_time(500, 'days') [(1, 'year'), (5, 'months'), (3, 'weeks'), (3, 'days')] """ result = [] unit = map(lambda a: a[1], NAMES).index(units) # Convert to seconds amount = amount * INTERVALS[unit] for i in range(len(NAMES)-1, -1, -1): a = amount / INTERVALS[i] if a > 0: result.append( (a, NAMES[i][1 % a]) ) amount -= a * INTERVALS[i] return result if __name__ == "__main__": import doctest doctest.testmod() 

您可以使用dateutil.relativedelta()来计算准确的时间增量,并使用此脚本进行人性化。

 def humanize_time(amount, units = 'seconds'): def process_time(amount, units): INTERVALS = [ 1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*7*4, 60*60*24*7*4*12, 60*60*24*7*4*12*100, 60*60*24*7*4*12*100*10] NAMES = [('second', 'seconds'), ('minute', 'minutes'), ('hour', 'hours'), ('day', 'days'), ('week', 'weeks'), ('month', 'months'), ('year', 'years'), ('century', 'centuries'), ('millennium', 'millennia')] result = [] unit = map(lambda a: a[1], NAMES).index(units) # Convert to seconds amount = amount * INTERVALS[unit] for i in range(len(NAMES)-1, -1, -1): a = amount // INTERVALS[i] if a > 0: result.append( (a, NAMES[i][1 % a]) ) amount -= a * INTERVALS[i] return result rd = process_time(int(amount), units) cont = 0 for u in rd: if u[0] > 0: cont += 1 buf = '' i = 0 for u in rd: if u[0] > 0: buf += "%d %s" % (u[0], u[1]) cont -= 1 if i < (len(rd)-1): if cont > 1: buf += ", " else: buf += " and " i += 1 return buf 

使用示例:

 >>> print humanize_time(234567890 - 123456789) 3 years, 9 months, 3 weeks, 5 days, 11 minutes and 41 seconds >>> humanize_time(9, 'weeks') 2 months and 1 week 

优势(您不需要第三方!)。

从“Liudmil Mitev”algorithm改进。 (谢谢!)

老问题,但我个人最喜欢这种做法:

 import datetime import math def human_time(*args, **kwargs): secs = float(datetime.timedelta(*args, **kwargs).total_seconds()) units = [("day", 86400), ("hour", 3600), ("minute", 60), ("second", 1)] parts = [] for unit, mul in units: if secs / mul >= 1 or mul == 1: if mul > 1: n = int(math.floor(secs / mul)) secs -= n * mul else: n = secs if secs != int(secs) else int(secs) parts.append("%s %s%s" % (n, unit, "" if n == 1 else "s")) return ", ".join(parts) human_time(seconds=3721) # -> "1 hour, 2 minutes, 1 second" 

如果你想用“和”分隔秒部分:

 "%s and %s" % tuple(human_time(seconds=3721).rsplit(", ", 1)) # -> "1 hour, 2 minutes and 1 second"