J’ai toujours été frustré par la gestion des dates du module datetime
.
Par exemple, la nécessité de toujours préciser l’année, le mois et le jour dans le mois pour obtenir une pauvre date.
Par exemple, si on veut connaître le jour de la Saint Valentin
>>> from datetime import date
>>> st_valentin = date(2019, 2, 14)
>>> st_valentin
datetime.date(2019, 2, 14)
>>> print(st_valentin)
2019-02-14
>>> print(st_valentin.month)
2
>>>
Avec ce module
>>> import aujourd
>>> from aujourd import *
>>> st_valentin = lejour(14, 2)
>>> st_valentin
date_fr(2019, 2, 14)
>>> print(st_valentin, st_valentin.mois)
jeudi 14 février 2019 2
>>>
Pour obtenir une sortie str(d)
qui ressemble à quelque chose avec datetime.date
il faut se plonger dans la documentation de d.strftime et ce n’est pas du gâteau !
Comme la classe date_fr
est dérivée de datetime.date
j’ai été obligé de conserver l’ordre annee, mois, jour dans le constructeur.
Il y a trois dates prédéfinies :
>>> print("Hier...", hier, aujourd.hui, demain)
Hier... mercredi 2 octobre 2019 jeudi 3 octobre 2019 vendredi 4 octobre 2019
>>>
des fonctions laveille
ou veille
et lendemain
>>> premier_mars = lejour(1, 3)
>>> print(veille(premier_mars))
jeudi 28 février 2019
Au lieu de lendemain(d)
on peut écrire 'd + unjour'
et le surlendemain est 'd + 2*unjour'
>>> print(premier_mars - 15*unjour)
jeudi 14 février 2019
>>> le15 = lejour(15)
>>> print(le15)
mardi 15 octobre 2019
Il y a une classe Semaine
avec un constructeur (jour [,mois[, annee]])
>>> semaine_du_14juillet = Semaine(14, 7)
>>> print(semaine_du_14juillet)
lundi 8 juillet 2019 ... dimanche 14 juillet 2019
>>> ssuivante = semaine_du_14juillet + 1
>>> print(ssuivante.vendredi)
vendredi 19 juillet 2019
Pratique pour se promener dans le calendier.
semaine en 8, et semaine en 15
>>> sc = semaine_courante()
>>> sp = sc + 1
>>> sem_en8 = sp + 1
>>> sem_en15 = sp + 2
>>> print(sp, '\n', sem_en8, '\n', sem_en15)
lundi 7 octobre 2019 ... dimanche 13 octobre 2019
lundi 14 octobre 2019 ... dimanche 20 octobre 2019
lundi 21 octobre 2019 ... dimanche 27 octobre 2019
>>>
>>> samedi_en8 = sem_en8.samedi
>>> print(samedi_en8)
samedi 19 octobre 2019
On peut iéter sur les jours de la semaine.
Le code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
r"""
aujourd.py module de manipulation des dates et des semaines.
import aujourd
from aujourd import *
print("Hier...", hier, aujourd.hui, demain)
print("avant hier, c'était le", laveille(hier))
surlendemain = lendemain(demain)
print("surlendemain", surlendemain)
print("dans 3 jours", aujourd.hui + 3 * unjour)
print("le 15 aout", lejour(15, 8))
st_valentin2020 = lejour(14, 2, 2020)
print("Saint Valentin", st_valentin2020)
d = sainte_catherine = lejour(25, 11)
print(d.jour, d.mois)
sc = semaine_courante()
print("la semaine courante", "numéro", sc.numero)
print(sc.tableau())
sp = sc + 1
print("vendredi de la semaine prochaine", sp.vendredi, '\n')
print("\net la nuit du 4 août, c'était quel jour ?")
s4aout = Semaine(4, 8, 1789)
print(s4aout.tableau(), '\n')
noel = lejour(25, 12)
semaine_de_noel = Semaine.fromdate(noel)
print("noel", noel, "semaine", semaine_de_noel.numero)
print(semaine_de_noel)
"""
from __future__ import print_function
__all__ = ( 'date_fr', 'Semaine', 'hui', 'hier', 'demain', 'date_enclair',
'unjour', 'lejour', 'laveille', 'veille', 'lendemain',
'semaine_courante', 'semaine_suivante', 'timedelta', 'Aujour' )
import datetime
from datetime import date, timedelta
import locale
locale.setlocale(locale.LC_TIME, locale.getdefaultlocale())
class date_fr(date):
"""une classe date qui tient compte de la locale
"""
def __str__(self):
s = date_enclair(self)
return s
def __repr__(self):
"""
à implémenter pour ne pas tomber sur date.__str__ par défaut
"""
s = super().__repr__()
return s
@property
def jour(self):
return self.day
@property
def mois(self):
return self.month
@property
def annee(self):
return self.year
def __add__(self, other):
""" date + delta """
d = super().__add__(other)
d = self.__class__(d.year, d.month, d.day)
return d
def __radd__(self, other):
""" delta + date -> date """
d = super().__radd__(other)
d = self.__class__(d.year, d.month, d.day)
return d
def __sub__(self, other):
"""
date2 - date1 -> deelta
date - delta -> date
"""
d = super().__sub__(other)
if not isinstance(d, timedelta):
d = self.__class__(d.year, d.month, d.day)
return d
hui = date_fr.today()
unjour = date.resolution # timedelta(1) ou date_fr.resolution
def veille(quand=None):
"""retourne la date de la veille
"""
if quand is None: quand = hui
return quand - unjour
laveille = veille
def lendemain(quand=None):
"""retourne la date du lendemain
"""
if quand is None: quand = hui
return quand + unjour
hier = laveille()
demain = hui + unjour
def date_enclair(d):
"""retourne la date d en clair, en tenat compte de la locale
"""
fmt = "%A %e %B %Y"
s = d.strftime(fmt)
return s
def lejour(jour, mois=None, annee=None):
"""retourne la date demandée, mois courant et année courante par défaut
le14juillet = lejour(14, 7)
sainte_catherine = lejour(25, 11)
saint_sylvestre = lejour(31, 12)
"""
if mois is None: mois = hui.month
if annee is None: annee = hui.year
t_ymd = annee, mois, jour
return date_fr(*t_ymd)
def Aujour(quand):
"""Seule l'expression "Aujour( aujourd.hui )" est possible
"""
if quand is not hui:
raise SyntaxError("the only valid expression is 'Aujour(aujourd.hui)'")
return quand
class Semaine(object):
"""
Semaine(jour, mois, annee) -> la semaine qui contient `jour` dans le mois
s14juillet = Semaine(14, 7) pour l'année en cours
bastille = Semaine(14, 7, 1789)
print(bastille.tableau())
for jour in bastille:
print(jour)
"""
def __init__(self, jour=None, mois=None, annee=None):
"""Semaine( 8 ) -> semaine qui contient le 8 du mois courant
bastille = Semaine(14, 7, 1789)
"""
if jour is None: jour = hui.day
d = lejour(jour, mois, annee)
idx = d.isoweekday()
if idx == 1:
self.lundi = d
else:
d = d - timedelta(idx - 1)
self.lundi = date_fr(d.year, d.month, d.day)
@classmethod
def fromdate(cls, d):
"""semaine qui contient la date d"""
return cls(d.day, d.month, d.year)
@property
def mardi(self):
return self.lundi + unjour
@property
def mercredi(self):
return self.lundi + timedelta(2)
@property
def jeudi(self):
return self.lundi + timedelta(3)
@property
def vendredi(self):
return self.lundi + timedelta(4)
@property
def samedi(self):
return self.lundi + timedelta(5)
@property
def dimanche(self):
"""dernier jour de la semaine"""
return self.lundi + timedelta(6)
@property
def numero(self):
"""numéro de la semaine entre 1 et 52"""
return self.lundi.isocalendar()[1]
@property
def du_au(self):
"""les dates (lundi, dimanche)
"""
return (self.lundi, self.dimanche)
def __str__(self):
s = " ... ".join( map(str, self.du_au))
return s
def __repr__(self):
""" Semaine(jour, mois, annee) """
d = self.lundi
s = "%s(%s, %s, %s)" % (self.__class__.__name__, d.day, d.month, d.year)
return s
# __iter__ __next__ ? automatique avec un générateur
def __iter__(self):
"""iteration protocol support
a generator function
"""
yield self.lundi
for i in range(1, 7):
yield self.lundi + timedelta(i)
def tableau(self):
"""tableau une ligne pour chaque jourde la semaine
"""
s = '\n'.join(map(str, iter(self)))
return s
def __eq__(self, other):
return self.lundi == other.lundi
def __ne__(self, other):
return self.lundi != other.lundi
def __lt__(self, other):
return self.lundi < other.lundi
def __te__(self, other):
return self.lundi <= other.lundi
def __gt__(self, other):
return self.lundi > other.lundi
def __ge__(self, other):
return self.lundi >= other.lundi
def __add__(self, n):
"""avancer de n semaines"""
d = self.lundi + timedelta(7*n)
return Semaine.fromdate(d)
def __sub__(self, n):
"""reculer de n semaines"""
d = self.lundi - timedelta(7*n)
return Semaine.fromdate(d)
def semaine_courante():
"""la semine courante"""
return Semaine.fromdate(hui)
# return Semaine(hui.day)
def semaine_suivante(sc=None):
"""La semaine qui suit sc, semaine_courante par défaut
on peut aussi écrire semaine + 1
"""
if sc is None: sc = semaine_courante()
d = sc.lundi + timedelta(7)
return Semaine.fromdate(d)
if __name__ == '__main__':
print(__doc__)
print("Hier...", hier, hui, demain)
print("avant hier, c'était le", laveille(hier), '\n')
surlendemain = lendemain(demain)
print("surlendemain", surlendemain)
print("dans 3 jours", hui + 3 * unjour, '\n')
print("le 15 aout", lejour(15, 8))
st_valentin2020 = lejour(14, 2, 2020)
print("Saint Valentin", st_valentin2020)
d = sainte_catherine = lejour(25, 11)
print(d.jour, d.mois)
sc = semaine_courante()
print("la semaine courante", "numéro", sc.numero)
print(sc.tableau(),'\n')
sp = sc + 1
print("vendredi de la semaine prochaine", sp.vendredi, '\n')
print("\net la nuit du 4 août, c'était quel jour ?")
s4aout = Semaine(4, 8, 1789)
print(s4aout.tableau(), '\n')
noel = lejour(25, 12)
semaine_de_noel = Semaine.fromdate(noel)
print("noel", noel, "semaine", semaine_de_noel.numero)
print(semaine_de_noel)
st_sylvestre = lejour(31, 12)
semx = Semaine.fromdate(st_sylvestre)
print("semaine de la Saint Sylvestre")
print(semx, "numero", semx.numero)
# vim: set shiftwidth=4 softtabstop=4 expandtab tabstop=4:
En espérant ne pas avoir fait d’erreur de copier/coller.
Cordialement,
Regards,
Mit freundlichen Grüßen,
مع تحياتي الخالصة
F. Petitjean
Ingénieur civil du Génie Maritime.
« On ne perd pas son temps en aiguisant ses outils. »
Proverbe français
« Moi, lorsque je n’ai rien à dire, je veux qu’on le sache. » (R. Devos)