[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [gulliver] Permanence agile ?


From Benjamin Cama <benoar at dolka dot fr>
Subject Re: [gulliver] Permanence agile ?
Date Fri, 04 Nov 2011 14:44:46 +0100

.. #!/usr/bin/env python
  # -*- coding: utf-8 -*-

Bonjour,

Le vendredi 04 novembre 2011 à 10:42 +0100, Frederic Daniel Luc Lehobey a écrit :

| >   Heu... non, justement, la règle des guilis pour « Geeks » est
| > beaucoup plus compliquée : il peut y avoir des mois à 5 vendredis.
| > C'est la raison (règle trop compliquée) pour laquelle je n'ai pas pu
| > pallier l'absence d'annonces des permanences dans l'agenda du libre.
| > J'ai proposé qu'on me donne la liste des dates des vendredis
| > concernés, mais cela n'amuse personne dans Gulliver semble-t-il...
| > (moi le premier). 
 
Pas du tout, ça m'amuse beaucoup, surtout si on peut le faire en python !

On peut par exemple utiliser le très utile module de gestion des dates et du temps ::

 import datetime

Je vais t'écrire une fonction pour trouver les 12 prochains derniers vendredi du mois ::

 def affiche_12_prochains_derniers_vendredi(a_la_date=datetime.date.today()):

   """Affiche les 12 prochains vendredi du mois à partir de la date
      `a_la_date`. Exemple :

      >>> affiche_12_prochains_derniers_vendredi(datetime.date(2011,11,4))
      2011-11-25
      2011-12-30
      2012-01-27
      2012-02-24
      2012-03-30
      2012-04-27
      2012-05-25
      2012-06-29
      2012-07-27
      2012-08-31
      2012-09-28
      2012-10-26
   """

À partir de la date `a_da_date`, on va chercher le début du mois, et définir
aussi une variable définissant la durée d'un jour ::

   debut_du_mois = a_la_date.replace(day=1)
   un_jour = datetime.timedelta(days=1)

Ensuite, on boucle douze fois, en prenant le mois suivant (on se retrouvera
donc au début du mois suivant), ce qui va nous permettre de revenir petit à
petit en arrière, en vérifiant si le jour est bien un vendredi ::

   for mois in range(12):
     # on avance d'un mois, en revenant à janvier quand on dépasse décembre
     debut_du_mois_prochain = debut_du_mois.replace(month=debut_du_mois.month%12+1)
     # si le mois prochain est inférieur au mois actuel, c'est qu'il faut changer d'année
     if debut_du_mois_prochain < debut_du_mois:
       debut_du_mois_prochain = debut_du_mois_prochain.replace(year=debut_du_mois.year+1)
     # on se place au dernier jour de mois courant
     dernier_vendredi = debut_du_mois_prochain - un_jour
     # tant qu'on est pas vendredi, on recule d'un jour
     while dernier_vendredi.weekday() != 4:
       dernier_vendredi -= un_jour

     print dernier_vendredi

     debut_du_mois = debut_du_mois_prochain

Et voilà.

Pour ceux qui se demandent pourquoi ce texte est étrange, c'est que c'est de la
« programmation lettrée » [1]_ en Python et reStructuredText_ avec PyLit_.
C'est à dire que cet email est un texte suivant les rèlgles de `rst` et pouvant
être converti en PDF, HTML, etc, mais c'est également le programme en
lui-même ! Et en plus, vous pouvez vérifier qu'il s'exécute bien selon sa
spécification que j'ai énoncé en commentaire au début de la fonction, qui est
un `doctest`_. Il est vérifié ainsi ::

 if __name__ == "__main__":
   import doctest
   doctest.testmod()

Pour lancer ce programme, utilisez PyLit pour en extraire le code, rendez le
résultat exécutable avec un petit `chmod +x` (ou lancez `python
le_fichier_résultant.py`) et admirez le résultat. Vous pouvez changer le test
contenu dans la spécification, et vous verrez bien un avertissement expliquant
que le programme n'est plus bon…

Ah oui, j'allais oublier, il faut bien lancer la fonction à un moment ::

   affiche_12_prochains_derniers_vendredi()

Et finalement, j'ai glissé un bug subtil dans ce programme, qui pourrait
apparaître si ce code était utilisé dans un programme qui tournerait assez
longtemps pour dépasser la date du dernier vendredi du mois à partir du moment
où il a été lancé. À vous de trouver.

Benjamin

.. [1] http://fr.wikipedia.org/wiki/Programmation_lettr%C3%A9e
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _PyLit: http://pylit.berlios.de/
.. _doctest: http://docs.python.org/library/doctest.html