2009-10-11 7 views

Odpowiedz

97

Kod został pierwotnie opublikowany na blogu „Python Dość Data funkcji” (http://evaisse.com/post/93417709/python-pretty-date-function)

Jest tu przytoczony jako konto blog został zawieszony, a strona nie jest już dostępna.

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" 
+3

które jest dostosowane do moich potrzeb. Dzięki! – flybywire

+2

Link już nie istnieje i daje zakaz. Potrzebujesz permlink tutaj lub treści do przeniesienia do tego postu. –

+0

@Chris: Dzięki za heads-up, i wciąż było w Google Cache, więc złapałem go. –

14

W poszukiwaniu samo z dodatkowego wymogu, aby obsłużyć przyszłych dat, znalazłem to: http://pypi.python.org/pypi/py-pretty/1

Przykład kodu (ze strony):

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' 
+1

Niestety, nie wygląda na to, że py-pretty zezwala na i18n . –

+1

Nie działa na Pythonie 3 albo ... zbyt źle –

1

Pisałem szczegółowy wpis na blogu dotyczący rozwiązania pod adresem http://sunilarora.org/17329071 Zamieszczam tu krótki opis.

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 
27

Jeśli zdarzy się przy użyciu Django ty, następnie nowego w wersji 1.4 jest filtr naturaltime szablon.

Aby z niego skorzystać, należy najpierw dodać 'django.contrib.humanize' z ustawieniami INSTALLED_APPS w settings.py i {% load humanize %} do szablonu, którego używasz filtra w.

Następnie w szablonie, jeśli masz zmienną datetime my_date , możesz wydrukować jego odległość od teraźniejszości, używając {{ my_date|naturaltime }}, która będzie renderowana jako coś w rodzaju 4 minutes ago.

Other new things in Django 1.4.

Documentation for naturaltime and other filters in the django.contrib.humanize set.

+0

Czy dodanie go do INSTALLED_APPS jest naprawdę konieczne? To działało bez tego dla mnie, chociaż użyłem filtra wewnątrz Pythona, a nie szablonu. Nice solution to template – aqs

4

Pakiet ago zapewnia to. Zadzwoń pod numer human na obiekcie datetime, aby uzyskać czytelny dla człowieka opis różnicy.

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 
3

Odpowiedź Jed Smith związana jest dobre, i używałem go przez rok lub tak, ale myślę, że to może być lepsze na kilka sposobów:

  • Miło jest być w stanie zdefiniuj każdą jednostkę czasu pod względem poprzedniej jednostki, zamiast stałych "magicznych", takich jak 3600, 86400 itd., które są rozproszone w całym kodzie.
  • Po długim użyciu stwierdzam, że nie chcę tak chętnie przechodzić do następnej jednostki. Przykład: zarówno 7 dni, jak i 13 dni będą wyświetlane jako "1 tydzień"; Wolałbym zamiast tego zobaczyć "7 dni" lub "13 dni".

Oto co wymyśliłem:

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

zauważyć, jak każda krotka w intervals jest łatwy do zinterpretowania i sprawdzić: a 'minute' jest 60 sekund; 'hour' jest 60 minut; itp.Jedynym krówką jest ustawienie wartości weeks_per_month na jej średnią wartość; biorąc pod uwagę wniosek, powinno być w porządku. (Należy zauważyć, że na pierwszy rzut oka widać, że trzy ostatnie stałe mnożą się do 365.242, liczba dni w roku.)

Jedną z wad mojej funkcji jest to, że nie robi nic poza "## units" "wzór:" Wczoraj "," właśnie teraz "itd. są już dostępne. Z drugiej strony, oryginalny plakat nie wymagał takich wyrażeń, więc wolę swoją funkcję ze względu na jego zwięzłość i czytelność stałych liczbowych. :)

+0

. Utrzymanie prostoty pozwala na wielokrotne użycie. E.g może użyć sufiksu dla względnego czasu 'value +" ago "' lub duration 'value +" left "' – swdev

0

To jest sedno @sunil „s po

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

Jest humanize package:

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

Obsługuje lokalizacja , umiędzynarodowienie :

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

Używanie obiekty datetime z 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) 
0

Możesz pobrać i zainstalować poniższy link. Powinien być bardziej przydatny dla ciebie. Od drugiego roku dostarcza przyjazną dla użytkownika wiadomość.

Jest dobrze przetestowany.

https://github.com/nareshchaudhary37/timestamp_content

poniższe kroki, aby zainstalować w swoim wirtualnym ENV.

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

Można również zrobić z arrow pakietu

Od github page:

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