简体   繁体   English

Python 中的用户友好时间格式?

[英]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 , internationalization :它支持本地化 ,国际

>>> _ = 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 链接的答案很好,我使用了一年左右,但我认为可以通过以下几种方式进行改进:

  • It's nice to be able to define each time unit in terms of the preceding unit, instead of having "magic" constants like 3600, 86400, etc. sprinkled throughout the code.能够根据前面的单位定义每个时间单位,而不是像 3600、86400 之类的“魔法”常量散布在整个代码中,这很好。
  • After much use, I find I don't want to go to the next unit quite so eagerly.多次使用后,我发现我不想那么急切地去下一个单元。 Example: both 7 days and 13 days will show as "1 week";示例:7 天和 13 天都将显示为“1 周”; I'd rather see "7 days" or "13 days" instead.我宁愿看到“7 天”或“13 天”。

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.

相关问题 Debian(raspberry pi)中用户友好的python代码编辑器 - user-friendly python code editor in debian (raspberry pi) 用于用户友好的任意字节字符串的配置文件格式是什么? - What config file format to use for user-friendly strings of arbitrary bytes? 使 Spotipy 程序用户友好 - Making Spotipy program user-friendly Python - 检查缺失库依赖项的用户友好方式的最佳实践? - Python - Best practice for user-friendly way of checking for missing library dependencies? Python请求异常处理:如何获取更多详细(用户友好)错误消息? - Python requests exception handling: How to get more verbose (user-friendly) error message? Django Python-以易于使用的方式向用户显示数据,包括通过views.py从models.py到HTML模板 - Django Python - Displaying data to user in user-friendly manner from models.py to HTML template through views.py 使用python的用户友好的日期格式 - user friendly date format using python 在Twitch机器人中添加帐户和更友好的集成 - Adding account and more user-friendly integration into Twitch bot 设置用户友好和显式标志值的最 Pythonic 方式? - Most Pythonic way of setting user-friendly and explicit flag values? 有没有办法将输入以预测 function 转换为分类数据,以便用户友好? - Is there a way to convert input to predict function into categorical data so it is user-friendly?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM