Python: Ajouter ou retrancher des mois à une date

A ma connaissance, en Python, à l'aide de la méthode timedelta du module datetime, il est très facile d'ajouter ou de retrancher des jours à une date mais quand il s'agit de le faire avec des mois, les choses se compliquent.
En effet tous les mois n'ayant pas le même nombre de jours, il devient incertain d'utiliser cette méthode.

J'ai donc développé cette fonction getNMonthsLessOrMore qui utilise à la fois le module datetime et le module calendar pour arriver au résultat souhaité.

from datetime import datetime
import calendar

def getNMonthsLessOrMore(startDate : datetime, nbMonths : int) -> list:

    class DateTimeFormat(Exception):
        pass

    class NbMonthsFormat(Exception):
        pass

    def getDayOfMonth(year, month, day):
        tmpCal = list(calendar.Calendar().itermonthdays(year, month))
        for x in range(day, 0, -1):
            if x in tmpCal: return x
        return 1

    try:
        if not isinstance(startDate, datetime): raise DateTimeFormat()
        if not isinstance(nbMonths, int): raise NbMonthsFormat()
    except DateTimeFormat:
        return False, "La date de départ doit être au format datetime.datetime"
    except NbMonthsFormat:
        return False, "Le nombre de mois doit être un entier positif ou négatif"
    else:
        if nbMonths == 0: return [startDate]
        L = []
        tmpDate = datetime(startDate.year, startDate.month, 1)
        if nbMonths < 0:
            for i in range(0, nbMonths, -1):
                y, m = calendar.prevmonth(tmpDate.year, tmpDate.month)
                tmpDate = datetime(y, m, getDayOfMonth(y, m, startDate.day))
                L.append(tmpDate)

        else:
            for i in range(0, nbMonths, 1):
                y, m = calendar.nextmonth(tmpDate.year, tmpDate.month)
                tmpDate = datetime(y, m, getDayOfMonth(y, m, startDate.day))
                L.append(tmpDate)
        return L

Exécution de la fonction:

>>> getNMonthsLessOrMore(datetime.now(), -6)
[datetime.datetime(2019, 12, 23, 0, 0), datetime.datetime(2019, 11, 23, 0, 0), datetime.datetime(2019, 10, 23, 0, 0), datetime.datetime(2019, 9, 23, 0, 0), datetime.datetime(2019, 8, 23, 0, 0), datetime.datetime(2019, 7, 23, 0, 0)]
>>> getNMonthsLessOrMore(datetime.now(), 8)
[datetime.datetime(2020, 2, 23, 0, 0), datetime.datetime(2020, 3, 23, 0, 0), datetime.datetime(2020, 4, 23, 0, 0), datetime.datetime(2020, 5, 23, 0, 0), datetime.datetime(2020, 6, 23, 0, 0), datetime.datetime(2020, 7, 23, 0, 0), datetime.datetime(2020, 8, 23, 0, 0), datetime.datetime(2020, 9, 23, 0, 0)]
>>> getNMonthsLessOrMore(datetime.now(), 0)
[datetime.datetime(2020, 1, 23, 7, 31, 43, 913244)]

Ajouter un commentaire

Filtered HTML

  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Tags HTML autorisés : <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Les lignes et les paragraphes vont à la ligne automatiquement.

Plain text

  • Aucune balise HTML autorisée.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Les lignes et les paragraphes vont à la ligne automatiquement.
CAPTCHA
Cette question permet de s'assurer que vous êtes un utilisateur humain et non un logiciel automatisé de pollupostage.
CAPTCHA visuel
Entrez les caractères (sans espace) affichés dans l'image.