[英]User-friendly time format in Python?
Python: I need to show file modification times in the "1 day ago", "two hours ago", format. Python:我需要以“1 天前”、“2 小时前”格式显示文件修改时间。
Is there something ready to do that?有什么东西可以这样做吗? It should be in English.它应该是英文的。
The code was originally published on a blog post "Python Pretty Date function" ( http://evaisse.com/post/93417709/python-pretty-date-function )该代码最初发布在博客文章“Python Pretty Date function”( http://evaisse.com/post/93417709/python-pretty-date-function )上
It is reproduced here as the blog account has been suspended and the page is no longer available.转载于此,因博客账号已被暂停,页面不再可用。
def pretty_date(time=False):
"""
Get a datetime object or a int() Epoch timestamp and return a
pretty string like 'an hour ago', 'Yesterday', '3 months ago',
'just now', etc
"""
from datetime import datetime
now = datetime.now()
if type(time) is int:
diff = now - datetime.fromtimestamp(time)
elif isinstance(time,datetime):
diff = now - time
elif not time:
diff = now - now
second_diff = diff.seconds
day_diff = diff.days
if day_diff < 0:
return ''
if day_diff == 0:
if second_diff < 10:
return "just now"
if second_diff < 60:
return str(second_diff) + " seconds ago"
if second_diff < 120:
return "a minute ago"
if second_diff < 3600:
return str(second_diff / 60) + " minutes ago"
if second_diff < 7200:
return "an hour ago"
if second_diff < 86400:
return str(second_diff / 3600) + " hours ago"
if day_diff == 1:
return "Yesterday"
if day_diff < 7:
return str(day_diff) + " days ago"
if day_diff < 31:
return str(day_diff / 7) + " weeks ago"
if day_diff < 365:
return str(day_diff / 30) + " months ago"
return str(day_diff / 365) + " years ago"
If you happen to be using Django , then new in version 1.4 is the naturaltime
template filter.如果您碰巧在使用Django ,那么 1.4 版中的新功能是naturaltime
模板过滤器。
To use it, first add 'django.contrib.humanize'
to your INSTALLED_APPS
setting in settings.py, and {% load humanize %}
into the template you're using the filter in.要使用它,首先将'django.contrib.humanize'
添加到 settings.py 中的INSTALLED_APPS
设置,然后将{% load humanize %}
到您正在使用过滤器的模板中。
Then, in your template, if you have a datetime variable my_date
, you can print its distance from the present by using {{ my_date|naturaltime }}
, which will be rendered as something like 4 minutes ago
.然后,在您的模板中,如果您有一个日期时间变量my_date
,您可以使用{{ my_date|naturaltime }}
打印它与现在的距离,这将呈现为类似4 minutes ago
。
Other new things in Django 1.4. Django 1.4 中的其他新东西。
Documentation for naturaltime
and other filters in the django.contrib.humanize
set. django.contrib.humanize
集中的naturaltime
和其他过滤器的文档。
In looking for the same thing with the additional requirement that it handle future dates, I found this: http://pypi.python.org/pypi/py-pretty/1在寻找具有处理未来日期的附加要求的相同内容时,我发现了这一点: http : //pypi.python.org/pypi/py-pretty/1
Example code (from site):示例代码(来自网站):
from datetime import datetime, timedelta
now = datetime.now()
hrago = now - timedelta(hours=1)
yesterday = now - timedelta(days=1)
tomorrow = now + timedelta(days=1)
dayafter = now + timedelta(days=2)
import pretty
print pretty.date(now) # 'now'
print pretty.date(hrago) # 'an hour ago'
print pretty.date(hrago, short=True) # '1h ago'
print pretty.date(hrago, asdays=True) # 'today'
print pretty.date(yesterday, short=True) # 'yest'
print pretty.date(tomorrow) # 'tomorrow'
You can also do that with arrow package你也可以用箭头包来做到这一点
From github page :从github 页面:
>>> import arrow >>> utc = arrow.utcnow() >>> utc = utc.shift(hours=-1) >>> utc.humanize() 'an hour ago'
There is humanize
package :有人性humanize
包:
>>> from datetime import datetime, timedelta
>>> import humanize # $ pip install humanize
>>> humanize.naturaltime(datetime.now() - timedelta(days=1))
'a day ago'
>>> humanize.naturaltime(datetime.now() - timedelta(hours=2))
'2 hours ago'
It supports localization l10n , internationalization i18n :它支持本地化l10n ,国际化 i18n :
>>> _ = humanize.i18n.activate('ru_RU')
>>> print humanize.naturaltime(datetime.now() - timedelta(days=1))
день назад
>>> print humanize.naturaltime(datetime.now() - timedelta(hours=2))
2 часа назад
The answer Jed Smith linked to is good, and I used it for a year or so, but I think it could be improved in a few ways: Jed Smith 链接的答案很好,我使用了一年左右,但我认为可以通过以下几种方式进行改进:
Here's what I came up with:这是我想出的:
def PrettyRelativeTime(time_diff_secs):
# Each tuple in the sequence gives the name of a unit, and the number of
# previous units which go into it.
weeks_per_month = 365.242 / 12 / 7
intervals = [('minute', 60), ('hour', 60), ('day', 24), ('week', 7),
('month', weeks_per_month), ('year', 12)]
unit, number = 'second', abs(time_diff_secs)
for new_unit, ratio in intervals:
new_number = float(number) / ratio
# If the new number is too small, don't go to the next unit.
if new_number < 2:
break
unit, number = new_unit, new_number
shown_num = int(number)
return '{} {}'.format(shown_num, unit + ('' if shown_num == 1 else 's'))
Notice how every tuple in intervals
is easy to interpret and check: a 'minute'
is 60
seconds;请注意intervals
每个元组如何易于解释和检查: 'minute'
是60
秒; an 'hour'
is 60
minutes;一个'hour'
是60
分钟; etc. The only fudge is setting weeks_per_month
to its average value;等等。唯一的weeks_per_month
是将weeks_per_month
设置为其平均值; given the application, that should be fine.鉴于应用程序,那应该没问题。 (And note that it's clear at a glance that the last three constants multiply out to 365.242, the number of days per year.) (请注意,一目了然,最后三个常数乘以 365.242,即每年的天数。)
One downside to my function is that it doesn't do anything outside the "## units" pattern: "Yesterday", "just now", etc. are right out.我的函数的一个缺点是它不会在“## 单位”模式之外做任何事情:“昨天”、“刚刚”等都已经过时了。 Then again, the original poster didn't ask for these fancy terms, so I prefer my function for its succinctness and the readability of its numerical constants.再说一次,原始海报并没有要求这些花哨的术语,所以我更喜欢我的函数,因为它的简洁性和数值常数的可读性。 :) :)
The ago package provides this. ago包提供了这一点。 Call human
on a datetime
object to get a human readable description of the difference.在datetime
对象上调用human
以获取人类可读的差异描述。
from ago import human
from datetime import datetime
from datetime import timedelta
ts = datetime.now() - timedelta(days=1, hours=5)
print(human(ts))
# 1 day, 5 hours ago
print(human(ts, precision=1))
# 1 day ago
Using datetime objects with tzinfo:将日期时间对象与 tzinfo 一起使用:
def time_elapsed(etime):
# need to add tzinfo to datetime.utcnow
now = datetime.utcnow().replace(tzinfo=etime.tzinfo)
opened_for = (now - etime).total_seconds()
names = ["seconds","minutes","hours","days","weeks","months"]
modulos = [ 1,60,3600,3600*24,3600*24*7,3660*24*30]
values = []
for m in modulos[::-1]:
values.append(int(opened_for / m))
opened_for -= values[-1]*m
pretty = []
for i,nm in enumerate(names[::-1]):
if values[i]!=0:
pretty.append("%i %s" % (values[i],nm))
return " ".join(pretty)
I have written a detailed blog post for the solution on http://sunilarora.org/17329071 I am posting a quick snippet here as well.我在http://sunilarora.org/17329071上为该解决方案写了一篇详细的博客文章,我也在这里发布了一个简短的片段。
from datetime import datetime
from dateutil.relativedelta import relativedelta
def get_fancy_time(d, display_full_version = False):
"""Returns a user friendly date format
d: some datetime instace in the past
display_second_unit: True/False
"""
#some helpers lambda's
plural = lambda x: 's' if x > 1 else ''
singular = lambda x: x[:-1]
#convert pluran (years) --> to singular (year)
display_unit = lambda unit, name: '%s %s%s'%(unit, name, plural(unit)) if unit > 0 else ''
#time units we are interested in descending order of significance
tm_units = ['years', 'months', 'days', 'hours', 'minutes', 'seconds']
rdelta = relativedelta(datetime.utcnow(), d) #capture the date difference
for idx, tm_unit in enumerate(tm_units):
first_unit_val = getattr(rdelta, tm_unit)
if first_unit_val > 0:
primary_unit = display_unit(first_unit_val, singular(tm_unit))
if display_full_version and idx < len(tm_units)-1:
next_unit = tm_units[idx + 1]
second_unit_val = getattr(rdelta, next_unit)
if second_unit_val > 0:
secondary_unit = display_unit(second_unit_val, singular(next_unit))
return primary_unit + ', ' + secondary_unit
return primary_unit
return None
This is the gist of @sunil 's post这是@sunil 帖子的要点
>>> from datetime import datetime
>>> from dateutil.relativedelta import relativedelta
>>> then = datetime(2003, 9, 17, 20, 54, 47, 282310)
>>> relativedelta(then, datetime.now())
relativedelta(years=-11, months=-3, days=-9, hours=-18, minutes=-17, seconds=-8, microseconds=+912664)
You can download and install from below link.您可以从以下链接下载并安装。 It should be more helpful for you.它应该对你更有帮助。 It has been providing user friendly message from second to year.从第二年到一年,它一直在提供用户友好的信息。
It's well tested.它经过了很好的测试。
https://github.com/nareshchaudhary37/timestamp_content https://github.com/nareshchaudhary37/timestamp_content
Below steps to install into your virtual env.以下步骤安装到您的虚拟环境中。
git clone https://github.com/nareshchaudhary37/timestamp_content
cd timestamp-content
python setup.py
Here is an updated answer based on Jed Smith's implementation that properly hands both offset-naive and offset-aware datetimes.这是基于 Jed Smith 的实现的更新答案,它正确地处理了偏移天真和偏移感知日期时间。 You can also give a default timezones.您还可以提供默认时区。 Python 3.5+. Python 3.5+。
import datetime
def pretty_date(time=None, default_timezone=datetime.timezone.utc):
"""
Get a datetime object or a int() Epoch timestamp and return a
pretty string like 'an hour ago', 'Yesterday', '3 months ago',
'just now', etc
"""
# Assumes all timezone naive dates are UTC
if time.tzinfo is None or time.tzinfo.utcoffset(time) is None:
if default_timezone:
time = time.replace(tzinfo=default_timezone)
now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
if type(time) is int:
diff = now - datetime.fromtimestamp(time)
elif isinstance(time, datetime.datetime):
diff = now - time
elif not time:
diff = now - now
second_diff = diff.seconds
day_diff = diff.days
if day_diff < 0:
return ''
if day_diff == 0:
if second_diff < 10:
return "just now"
if second_diff < 60:
return str(second_diff) + " seconds ago"
if second_diff < 120:
return "a minute ago"
if second_diff < 3600:
return str(second_diff / 60) + " minutes ago"
if second_diff < 7200:
return "an hour ago"
if second_diff < 86400:
return str(second_diff / 3600) + " hours ago"
if day_diff == 1:
return "Yesterday"
if day_diff < 7:
return str(day_diff) + " days ago"
if day_diff < 31:
return str(day_diff / 7) + " weeks ago"
if day_diff < 365:
return str(day_diff / 30) + " months ago"
return str(day_diff / 365) + " years ago"
I've been dragging and tweaking this code from programming language to programming language for so long, I don't remember where I originally got it from.我一直在从编程语言到编程语言拖拽和调整这段代码很长时间,我不记得我最初从哪里得到它。 It served me well in PHP, Java, and TypeScript, and now it's time for Python.它在 PHP、Java 和 TypeScript 方面对我很有帮助,现在是 Python 的时候了。
It handles past and future dates, as well as edge cases.它处理过去和未来的日期,以及边缘情况。
def unix_time() -> int:
return int(time.time())
def pretty_time(t: int, absolute=False) -> str:
if not type(t) is int:
return "N/A"
if t == 0:
return "Never"
now = unix_time()
if t == now:
return "Now"
periods = ["second", "minute", "hour", "day", "week", "month", "year", "decade"]
lengths = [60, 60, 24, 7, 4.35, 12, 10]
diff = now - t
if absolute:
suffix = ""
else:
if diff >= 0:
suffix = "ago"
else:
diff *= -1
suffix = "remaining"
i = 0
while diff >= lengths[i] and i < len(lengths) - 1:
diff /= lengths[i]
i += 1
diff = round(diff)
if diff > 1:
periods[i] += "s"
return "{0} {1} {2}".format(diff, periods[i], suffix)
DAY_INCREMENTS = [
[365, "year"],
[30, "month"],
[7, "week"],
[1, "day"],
]
SECOND_INCREMENTS = [
[3600, "hour"],
[60, "minute"],
[1, "second"],
]
def time_ago(dt):
diff = datetime.now() - dt # use timezone.now() or equivalent if `dt` is timezone aware
if diff.days < 0:
return "in the future?!?"
for increment, label in DAY_INCREMENTS:
if diff.days >= increment:
increment_diff = int(diff.days / increment)
return str(increment_diff) + " " + label + plural(increment_diff) + " ago"
for increment, label in SECOND_INCREMENTS:
if diff.seconds >= increment:
increment_diff = int(diff.seconds / increment)
return str(increment_diff) + " " + label + plural(increment_diff) + " ago"
return "just now"
def plural(num):
if num != 1:
return "s"
return ""
def time_ago(self):
start_time = self.date # The start date
now_time = datetime.now()
difference = int((now_time - start_time).total_seconds())
second = [1, 'seconds']
minute = [60, 'minutes']
hour = [60 * minute[0], 'hours']
day = [24 * hour[0], 'days']
week = [7 * day[0], 'weeks']
month = [4 * week[0], 'months']
year = [12 * month[0], 'years']
times = [year, month, week, day, hour, minute, second]
for time in times:
if difference >= time[0]:
time_ago = int(difference / time[0])
if time_ago <= 1:
timeframe = time[1].rstrip('s')
else:
timeframe = time[1]
time_item = str(time_ago) + ' ' + timeframe
return time_item
return 'Date Error'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.