Удобный формат времени в Python?


Python: мне нужно показать время изменения файла в формате "1 день назад", "два часа назад".

есть ли что-то готовое для этого? Это должно быть на английском языке.

11 52

11 ответов:

код был первоначально опубликован в блоге "Python Pretty Date function" (http://evaisse.com/post/93417709/python-pretty-date-function)

он воспроизводится здесь, поскольку учетная запись блога была приостановлена, и страница больше не доступна.

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"

если вы случайно используете Джанго, то новое в версии 1.4 является naturaltime фильтр шаблон.

, чтобы использовать его, сначала добавьте 'django.contrib.humanize' на INSTALLED_APPS установка внутри settings.py и {% load humanize %} в шаблон, в котором вы используете фильтр.

затем, в вашем шаблоне, если у вас есть переменная datetime my_date, вы можете распечатать его удаленности от настоящего с помощью {{ my_date|naturaltime }}, который будет показан как что-то вроде 4 minutes ago.

другой новые вещи в Django 1.4.

документация naturaltime и другие фильтры в django.contrib.humanize set.

в поисках того же самого с дополнительным требованием, чтобы он обрабатывал будущие даты, я нашел это: http://pypi.python.org/pypi/py-pretty/1

пример кода (на сайте):

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'

ответ Джед Смит связан с это хорошо, и я использовал его в течение года или около того, но я думаю, что это может быть улучшена несколькими способами:

  • приятно иметь возможность определять каждую единицу времени в терминах предыдущей единицы, вместо того, чтобы иметь "волшебные" константы, такие как 3600, 86400 и т. д. разбросанных по всему коду.
  • после Большого использования, я нахожу, что я не хочу идти к следующему блоку так охотно. Пример: как 7 дней, так и 13 дней будут отображаться как "1 неделя"; я бы предпочел увидеть " 7 дней" или "13 дней" вместо.

вот что я придумал:

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'))

обратите внимание, как каждый Кортеж в intervals легко интерпретировать и проверить: a 'minute' и 60 секунд;'hour' и 60 минуты; etc. Единственная выдумка-это установка weeks_per_month к его среднему значению; учитывая приложение, это должно быть хорошо. (И обратите внимание, что с первого взгляда ясно, что последние три константы умножаются на 365.242, количество дней в году.)

один недостатком моей функции является то, что она ничего не делает за пределами шаблона "## units": "вчера", "только сейчас" и т. д. сейчас выйдем. Опять же, оригинальный плакат не просил этих причудливых терминов, поэтому я предпочитаю свою функцию за ее лаконичность и читаемость ее числовых констант. :)

вы также можете сделать это с стрелка пакета

С страница github:

>>> import arrow
>>> utc = arrow.utcnow()
>>> utc = utc.replace(hours=-1)
>>> local.humanize()
'an hour ago'

The назад пакет обеспечивает это. Звоните human на datetime объект, чтобы получить читаемое человеком описание разницы.

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

здесь 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'

Он поддерживает локализации l10n, интернационализация i18n:

>>> _ = humanize.i18n.activate('ru_RU')
>>> print humanize.naturaltime(datetime.now() - timedelta(days=1))
день назад
>>> print humanize.naturaltime(datetime.now() - timedelta(hours=2))
2 часа назад

Я написал подробный пост в блоге для решения на 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

использование объектов datetime с tzinfo:

def time_elapsed(etime):
    # need to add tzinfo to datetime.utcnow
    now = datetime.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)

Это суть сообщения @sunil ' s

>>> 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)

вы можете скачать и установить по ссылке ниже. Это должно быть более полезным для вас. Он предоставляет удобное для пользователя сообщение от второго до года.

Это хорошо проверенный.

https://github.com/nareshchaudhary37/timestamp_content

ниже шаги для установки в ваш виртуальный env.

git clone https://github.com/nareshchaudhary37/timestamp_content
cd timestamp-content
python setup.py