Manipuler les dates et les durées en Python 2


Manipuler des dates, c’est chaud. Le calendrier, c’est plein de subtilités comme les années bissextiles, les mois qui ont 4 possibilités de nombre de jours, les semaines qui commencent un dimanche aux US et un lundi en France… Autant dire que faire ça à la mano, c’est pas marrant, marrant.

Avec les modules datetimes et calendar, c’est déjà plus cool.

Date et heure

Datetime est un module qui permet de manipuler des dates et des durées sous forme d’objets. L’idée est simple: vous manipulez l’objet pour faire tous vos calculs, et quand vous avez besoin de l’afficher, vous formatez l’objet en chaîne de caractères.

On peut créer artificiellement un objet datetime, ses paramètres sont:

datetime(année, mois, jour, heure, minute, seconde, microseconde, fuseau horaire)

Mais seuls “année”, “mois” et “jour” sont obligatoires.

>>> from datetime import datetime
>>> datetime(2000, 1, 1)
datetime.datetime(2000, 1, 1, 0, 0)

Nous sommes ici le premier janvier 2000, à la seconde et la minute zéro, de l’heure zéro.

On peut bien entendu récupérer l’heure et la date du jour:

>>> maintenant = datetime.now()
>>> maintenant
datetime.datetime(2012, 12, 24, 18, 20, 4, 534918)
>>> maintenant.year
2012
>>> maintenant.month
12
>>> maintenant.day
24
>>> maintenant.hour
18
>>> maintenant.minute
20
>>> maintenant.second
4
>>> maintenant.microsecond
534918
>>> maintenant.isocalendar() # année, semaine, jour
(2012, 52, 2)

Enfin, si vous souhaitez uniquement vous occuper de la date ou de l’heure:

>>> from datetime import date, time, datetime
>>> date(2000, 1, 1)
datetime.date(2000, 1, 1)
>>> time(12, 12, 12)
datetime.time(12, 12, 12)
>>> maintenant = datetime.now()
>>> maintenant.date()
datetime.date(2012, 12, 25)
>>> maintenant.time()
datetime.time(15, 2, 16, 704000)

Notez que j’écris cet article le jour de Noël, en famille. Et que là mon frangin est en train d’aider ma mère à éplucher des pommes tandis que je les regarde de loin. C’est mal. Je vais leur donner un coup de main et je reviens.

*Sam épluche les pommes et s’efforce de se tenir éloigné du débat sur la condition des canards gavés pour leur foie. Il quitte la table discrètement dès le premier usage de wikipédia pour défendre les volatiles*

Back.

Je disais donc…

Durée

En plus de pouvoir récupérer la date du jour, on peut calculer la différence entre deux dates. Par exemple, combien de temps y a-t-il entre aujourd’hui et le premier jour de l’an 2000 ?

>>> duree = datetime.now() - datetime(2000, 1, 1)
>>> duree
datetime.timedelta(4741, 66999, 829132)

Et vous découvrez ici un autre objet: le timedelta. Cet objet représente une durée en jours, secondes et microsecondes.

>>> duree.days
4741
>>> duree.seconds
67007
>>> duree.mi
duree.microseconds  duree.min
>>> duree.microseconds
943760
>>> duree.total_seconds() # addition de toutes les secondes + les jours
409689407.94376

On peut créer son propre timedelta:

>>> timedelta(days=3, seconds=100)
datetime.timedelta(3, 100)

Cela permet de répondre à la question : “Quelle date serons-nous dans 2 jours, 4 heures, 3 minutes, et 12 secondes ?”:

>>> datetime.now() + timedelta(days=2, hours=4, minutes=3, seconds=12)
datetime.datetime(2012, 12, 26, 22, 44, 6, 251071)

A chaque fois, un nouvel objet est retourné. En effet, les objets datetime et timedelta sont immutables. Ainsi si vous voulez utiliser une version légèrement différente d’un objet datetime, il faudra toujours en créer un nouveau. Par exemple:

>>> maintenant = datetime.now()
>>> maintenant.replace(year=1995) # on créer un nouvel objet
datetime.datetime(1995, 12, 25, 0, 9, 46, 185000)

Vous noterez que je ne parles pas de fuseau horaire. Et bien c’est parce que l’implémentation Python est particulièrement ratée : l’API est compliquée et les données ne sont pas à jour. Il faut dire que la mesure du temps, contrairement à ce qu’on pourrait penser, n’est pas vraiment le truc le plus stable du monde, et des pays changent régulièrement leur manière de faire.

Donc je trollerai sur fuseaux dans un article plus gluant sur lequel, une fois n’est pas coutume, je taclerai Python. Restons sur les dates pures.

Autre modules

Une fois que vous maitrisez datetime, vous pouvez retourner lire notre article sur le formatage de date.

Mais ce n’est pas tout, il y d’autres modules liés à la gestion du temps en Python.

Dans la lib standard, il y a calendar.

Il permet de manipuler un calendrier comme un objet, et itérer sur les jours d’un mois, les semaines, vérifier les caractéristiques d’un jour en particulier, etc. :

>>> import calendar
>>> calendar.mdays # combien de jour par mois ?
[0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
>>> calendar.isleap(2000) # est-ce une année bissextile ?
True
>>> calendar.weekday(2000, 1, 1) # quel jour était cette date ?
5
>>> calendar.MONDAY, calendar.TUESDAY, calendar.WEDNESDAY, calendar.THURSDAY, calendar.FRIDAY, calendar.SATURDAY, calendar.SUNDAY 
(0, 1, 2, 3, 4, 5, 6)

On peut instancier un calendrier et itérer dessus:

>>> cal = calendar.Calendar()
>>> cal.getfirstweekday()
0
>>> list(cal.iterweekdays())
[0, 1, 2, 3, 4, 5, 6]
>>> list(cal.itermonthdays(2000, 1)) 
[0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0]
>>> list(cal.itermonthdates(2000, 1))
[datetime.date(1999, 12, 27), datetime.date(1999, 12, 28), datetime.date(1999, 12, 29), datetime.date(1999, 12, 30), datetime.date(1999, 12, 31), datetime.date(2000, 1, 1), datetime.date(2000, 1, 2), datetime.date(2000, 1, 3), datetime.date(2000, 1, 4), datetime.date(2000, 1, 5), datetime.date(2000, 1, 6), datetime.date(2000, 1, 7), datetime.date(2000, 1, 8), datetime.date(2000, 1, 9), datetime.date(2000, 1, 10), datetime.date(2000, 1, 11), datetime.date(2000, 1, 12), datetime.date(2000, 1, 13), datetime.date(2000, 1, 14), datetime.date(2000, 1, 15), datetime.date(2000, 1, 16), datetime.date(2000, 1, 17), datetime.date(2000, 1, 18), datetime.date(2000, 1, 19), datetime.date(2000, 1, 20), datetime.date(2000, 1, 21), datetime.date(2000, 1, 22), datetime.date(2000, 1, 23), datetime.date(2000, 1, 24), datetime.date(2000, 1, 25), datetime.date(2000, 1, 26), datetime.date(2000, 1, 27), datetime.date(2000, 1, 28), datetime.date(2000, 1, 29), datetime.date(2000, 1, 30), datetime.date(2000, 1, 31), datetime.date(2000, 2, 1), datetime.date(2000, 2, 2), datetime.date(2000, 2, 3), datetime.date(2000, 2, 4), datetime.date(2000, 2, 5), datetime.date(2000, 2, 6)]
>>> cal.monthdayscalendar(2000, 1)
[[0, 0, 0, 0, 0, 1, 2], [3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15, 16], [17, 18, 19, 20, 21, 22, 23], [24, 25, 26, 27, 28, 29, 30], [31, 0, 0, 0, 0, 0, 0]]

Comme souvent Python vient aussi avec de très bons modules tierces parties pour manipuler les dates:

  • dateutils est un datetime boosté aux hormones qui permet notamment de donnée des durées floues comme “+ 1 mois” et gérer des événements qui se répètent. Il est dans tous mes projets par défaut.
  • babel n’est pas spécialisé dans les dates mais dans la localisation. Le module possède des outils pour formater des dates selon le format de chaque pays, et aussi avec des formats naturels comme “il y a une minute”.
  • pytz est une implémentation saine de gestion des fuseaux horaires en Python. On y reviendra.

2 thoughts on “Manipuler les dates et les durées en Python

  • Drife

    Un article toujours d’actualité pour gérer ces %µ£* de dates en Python !

    Du coup, c’est peut-être valable de corriger les fautes ^^ ?

    fuseaux horaire -> fuseau horaire

    je ne parles -> je ne parle

    fuseaux horaire (le 2ème) -> fuseaux horaires

    d’autres modules liées -> d’autres modules liés

    verifier -> vérifier

    notament de donnée -> notamment de donner

    Le module possèdes -> Le module possède

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.