38 votes

Jours naturels/relatifs en Python

J'aimerais avoir un moyen d'afficher les temps naturels pour des éléments datés en Python. Un peu comme Twitter affiche un message datant d'"il y a un instant", "il y a quelques minutes", "il y a deux heures", "il y a trois jours", etc.

Django 1.0 a une méthode "humanize" dans django.contrib. Je n'utilise pas le framework Django, et même si c'était le cas, il est plus limité que ce que je souhaiterais.

Merci de me faire savoir (ainsi qu'à des générations de futurs chercheurs) s'il existe déjà une bonne solution opérationnelle. Comme il s'agit d'une tâche assez courante, j'imagine qu'il doit y avoir quelque chose.

0 votes

J'ai trouvé ceci : code.google.com/p/parsedatetime Mais cela semble être pour analyser de nombreuses formes différentes de dates, alors que je suis simplement intéressé par le formatage d'un objet datetime.

38voto

Josh Segall Points 1996

Les dates de Twitter en particulier sont intéressantes parce qu'elles ne sont relatives qu'au premier jour. Après 24 heures, elles n'indiquent que le mois et le jour. Après un an, elles commencent à afficher les deux derniers chiffres de l'année. Voici un exemple de fonction qui fait quelque chose de plus proche des dates relatives de Twitter, bien qu'elle affiche toujours l'année aussi après 24 heures. Cette fonction ne s'applique qu'aux États-Unis, mais vous pouvez toujours la modifier selon vos besoins.

# 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 votes

Votre solution est de loin la plus petite et la plus élégante. Elle implique simplement que nous devons traduire toutes les chaînes de caractères. Mais je la retiens, merci !

20voto

runeh Points 1304

Bien qu'elles ne vous soient pas utiles en ce moment même, elles pourraient l'être pour de futurs chercheurs : Le module babel, qui gère toutes sortes de paramètres linguistiques, dispose d'une fonction permettant de faire plus ou moins ce que vous souhaitez. Pour l'instant, cette fonction ne se trouve que dans leur tronc, et non dans la dernière version publique (version 0.9.4). Une fois que la fonctionnalité sera disponible dans une version, vous pourrez faire quelque chose comme :

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

Ceci est tiré directement de la documentation babel sur le formatage du delta temporel . Cela vous permettra au moins de faire une partie du chemin. Il n'y aura pas de flou au niveau de "il y a quelques instants" et autres, mais il y aura "n minutes", etc. au pluriel.

Pour ce que cela vaut, le module babel contient également des fonctions de formatage des dates et des heures en fonction de la localisation, ce qui peut s'avérer utile lorsque le décalage horaire est important.

0 votes

Comment faire la même chose avec Python 3 si python3-babel n'est pas disponible dans les dépôts de la distribution ? Merci de votre compréhension.

11voto

sevenforce Points 599

Il y a le paquet humaniser :

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

Exemples de cas d'utilisation :

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

En outre (voir le lien ci-dessus), il soutient également l'humanisation de l'économie :

  • entiers
  • taille des fichiers
  • flottants (vers les nombres fractionnaires)

8voto

lpfavreau Points 5622

Ou vous pouvez facilement adapter timesince.py de Django qui n'a que 2 autres dépendances : une pour la traduction (dont vous n'aurez peut-être pas besoin) et une pour les fuseaux horaires (qui peut être facilement adaptée).

A ce propos, Django a une licence BSD qui est assez flexible, vous pourrez l'utiliser dans n'importe quel projet que vous êtes en train d'utiliser.

5voto

lpfavreau Points 5622

Vous cherchez quelque chose comme ceci (Impression de dates relatives en Python) ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X