[英]How can I produce a human readable difference when subtracting two UNIX timestamps using Python?
這個問題類似於這個關於用 Python 減去日期的問題,但不完全相同。 我不是在處理字符串,我必須找出兩個紀元時間戳之間的差異,並以人類可讀的格式產生差異。
例如:
32 Seconds
17 Minutes
22.3 Hours
1.25 Days
3.5 Weeks
2 Months
4.25 Years
或者,我想表達這樣的區別:
4 years, 6 months, 3 weeks, 4 days, 6 hours 21 minutes and 15 seconds
我不認為我可以使用strptime
,因為我正在處理兩個紀元日期的差異。 我可以寫一些東西來做到這一點,但我很確定已經寫了一些我可以使用的東西。
什么模塊合適? 我只是錯過了一些time
嗎? 我進入 Python 的旅程才真正開始,如果這確實是重復的,那是因為我沒有弄清楚要搜索的內容。
為了准確性,我真的最關心當年的日歷。
您可以使用出色的dateutil模塊及其相關的 delta class:
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 的解決方案進行了一些改進。 在復數實體的情況下也顯示復數(如小時)
導入相關增量
>>> from dateutil.relativedelta import relativedelta
一個 lambda function
>>> attrs = ['years', 'months', 'days', 'hours', 'minutes', 'seconds']
>>> human_readable = lambda delta: ['%d %s' % (getattr(delta, attr), attr if getattr(delta, attr) > 1 else 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']
我今天早些時候遇到了完全相同的問題,我在標准庫中找不到任何我可以使用的東西,所以這就是我寫的:
#!/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”算法。 (謝謝!)
查看人性化 package
https://github.com/jmoiron/humanize
import datetime
humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=1))
'a second ago'
humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600))
'an hour ago'
老問題,但我個人最喜歡這種方法:
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"
這是一個較短的時間間隔,以秒為單位,一天之內 (t<86400)。 如果您使用 unix 時間戳(自紀元以來的秒數,UTC),則很有用。
t = 45678
print('%d hours, %d minutes, %d seconds' % (t//3600, t%3600//60, t%60))
可能會進一步延長 (t//86400, ...)。
一個非常古老的問題,但我發現這個解決方案在 Python3 中似乎非常簡單:
print(datetime.timedelta(seconds=3600))
# output: 1:00:00
print(datetime.timedelta(hours=360.1245))
# output: 15 days, 0:07:28.200000
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.