[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