2009-01-04 14 views
35

Me gustaría una forma de mostrar los tiempos naturales de los elementos con fecha en Python. Similar a cómo Twitter mostrará un mensaje de "hace un momento", "hace unos minutos", "hace dos horas", "hace tres días", etc.Días naturales/relativos en Python

Django 1.0 tiene un método "humanizar" en django .contrib. No estoy usando el framework Django, y aunque lo fuera, es más limitado de lo que me gustaría.

Por favor, permítanme (y las generaciones de futuros buscadores) saber si ya hay una buena solución de trabajo. Como esta es una tarea bastante común, imagino que debe haber algo.

+0

encontré esto: http://code.google.com/p/parsedatetime/ Pero esto parece ser para analizar muchas formas diferentes de fechas , mientras que simplemente estoy interesado en formatear un objeto datetime. – jamtoday

Respuesta

16

Si bien no es útil para usted en este momento, puede serlo para futuros buscadores: El módulo babel, que trata con todo tipo de cosas locales, tiene una función para hacer más o menos lo que desee. Actualmente, solo está en su troncal, no en el último lanzamiento público (versión 0.9.4). Una vez que las tierras de funcionalidad en un comunicado, se podría hacer algo como:

from datetime import timedelta 
from babel.dates import format_timedelta 
delta = timedelta(days=6) 
format_timedelta(delta, locale='en_US') 
u'1 week' 

Esto se toma directamente de the babel documentation on time delta formatting. Esto al menos te llevará partes del camino. No hará borrosidad hasta el nivel de "momentos atrás" y tal, pero hará "n minutos" etc. correctamente pluralizados.

Por lo que vale, el módulo babel también contiene funciones para formatear fechas y horas de acuerdo con la configuración regional, lo que podría ser útil cuando la delta del tiempo es grande.

+0

Cómo hacer igual en Python 3 si python3-babel no está disponible en los repositorios de distribuciones? Gracias. –

7

O podría adaptar fácilmente timesince.py de Django que solo tiene otras 2 dependencias: una para la traducción (que puede que no necesite) y otra para las zonas horarias (que se pueden adaptar fácilmente).

Por cierto, Django has a BSD license que es bastante flexible, podrá usarlo en cualquier proyecto que esté utilizando actualmente.

35

Las fechas de Twitter en específico son interesantes porque son relativas solo para el primer día. Después de 24 horas, solo muestran el mes y el día. Después de un año comienzan a mostrar los últimos dos dígitos del año. Aquí hay una función de muestra que hace algo más parecido a las fechas relativas de Twitter, aunque siempre muestra el año también después de 24 horas. Es solo la configuración regional de EE. UU., Pero siempre puede modificarla según sea necesario.

# tested in Python 2.7 
import datetime 
def prettydate(d): 
    diff = datetime.datetime.utcnow() - d 
    s = diff.seconds 
    if diff.days > 7 or diff.days < 0: 
     return d.strftime('%d %b %y') 
    elif diff.days == 1: 
     return '1 day ago' 
    elif diff.days > 1: 
     return '{} days ago'.format(diff.days) 
    elif s <= 1: 
     return 'just now' 
    elif s < 60: 
     return '{} seconds ago'.format(s) 
    elif s < 120: 
     return '1 minute ago' 
    elif s < 3600: 
     return '{} minutes ago'.format(s/60) 
    elif s < 7200: 
     return '1 hour ago' 
    else: 
     return '{} hours ago'.format(s/3600) 
+0

Su solución es, con mucho, el más pequeño y más elegante. Simplemente implica que tenemos que traducir todas las cadenas. Pero tomaré ese, ¡gracias! –

7

Hay the humanize package:

>>> import humanize 
>>> import datetime 
>>> humanize.naturalday(datetime.datetime.now()) 
'today' 
>>> humanize.naturalday(datetime.datetime.now() - datetime.timedelta(days=1)) 
'yesterday' 
>>> humanize.naturalday(datetime.date(2007, 6, 5)) 
'Jun 05' 
>>> humanize.naturaldate(datetime.date(2007, 6, 5)) 
'Jun 05 2007' 
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=1)) 
'a second ago' 
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600)) 
'an hour ago' 

Ejemplos para su caso de uso:

>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=36000)) 
'10 hours ago' 
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=360000)) 
'4 days ago' 
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600000)) 
'a month ago' 

adicionales (ver enlace más arriba) también es compatible con la humanización de:

  • enteros
  • tamaño de los archivos
  • flotadores (a los números fraccionarios)
Cuestiones relacionadas