Удобный формат времени в Python?
Python: мне нужно показать время изменения файла в формате "1 день назад", "два часа назад".
есть ли что-то готовое для этого? Это должно быть на английском языке.
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": "вчера", "только сейчас" и т. д. сейчас выйдем. Опять же, оригинальный плакат не просил этих причудливых терминов, поэтому я предпочитаю свою функцию за ее лаконичность и читаемость ее числовых констант. :)
вы также можете сделать это с стрелка пакета
>>> 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