web-dev-qa-db-fra.com

Comment calculer la date six mois à compter de la date actuelle à l'aide du module datetime Python?

J'utilise le module datetime Python. Je cherche à calculer la date 6 mois à partir de la date actuelle. Quelqu'un pourrait-il me donner un peu d'aide pour ce faire?

La raison pour laquelle je veux générer une date à 6 mois de la date actuelle est de produire un date de révision. Si l'utilisateur entre des données dans le système, sa date de révision est de 6 mois à compter de la date à laquelle elles ont été entrées.

312
RailsSon
import datetime
print (datetime.date.today() + datetime.timedelta(6*365/12)).isoformat()
15
kmkaplan

J'ai trouvé cette solution bien. (Ceci utilise le extension python-dateutil )

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

L'avantage de cette approche est qu'elle traite les problèmes avec 28, 30, 31 jours, etc. Cela devient très utile pour gérer les règles et les scénarios de gestion (par exemple, la génération de factures, etc.).

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)
899
Mahendra

Cela dépend de ce que vous entendez par 6 mois à compter de la date du jour.

  1. En utilisant des mois naturels:

    (day, month, year) = (day, (month+6)%12, year+(month+6)/12)
    
  2. En utilisant la définition d'un banquier, 6 * 30:

    date += datetime.timedelta(6*30)
    
46
vartec

Pour le calcul de début de mois en mois:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
17
breddi

Avec Python 3.x, vous pouvez le faire comme ceci:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

mais vous devrez installer le module python-dateutil:

pip install python-dateutil
15
Luka Lopusina

Qu'entendez-vous par "6 mois"? Est-ce que 2009-02-13 + 6 mois == 2009-08-13 ou s'agit-il de 2009-02-13 + 6 * 30 jours?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

Plus d'infos sur mx.DateTime

14
Johannes Weiss

Je sais que c'était pour 6 mois, mais la réponse montre dans Google pour "ajouter des mois en python" si vous ajoutez un mois:

import calendar

date = datetime.date.today()    //Or your date

datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

cela compterait les jours du mois en cours et les ajouterait à la date actuelle; utiliser 365/12 avec 1/12 d'année risquerait de poser des problèmes pour des mois plus ou moins longs si vous répétiez cette date.

12
Mike Davies

Voici donc un exemple de dateutil.relativedelta que j’ai trouvé utile pour parcourir l’année écoulée, en sautant un mois à la date actuelle:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

Comme pour les autres réponses, vous devez comprendre ce que vous entendez par "dans 6 mois". Si vous voulez dire "le jour du mois d'aujourd'hui dans six ans", voici ce que vous feriez:

datetime.datetime.now() + relativedelta(months=6)
12
dannyman

Cette solution fonctionne correctement pour décembre, ce que la plupart des réponses sur cette page ne font pas. Vous devez d’abord décaler les mois de la base 1 (janvier = 1) à la base 0 (janvier = 0) avant d’utiliser le module (%) ou la division entière (//), sinon novembre (11) plus un mois vous en donne 12 qui, en trouvant le reste (12% 12), donne 0.

(Et ne suggérez pas "(mois% 12) + 1" ou octobre + 1 = décembre!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = d.year + ((( d.month - 1) + x ) / 12 ) 
    return datetime.date( newyear, newmonth, d.day)

Cependant ... Cela ne rend pas compte d'un problème comme le 31 janvier + un mois. Nous revenons donc à l'OP - qu'entendez-vous par l'ajout d'un mois? Une solution consiste à revenir en arrière jusqu'à ce que vous obteniez un jour valide, étant donné que la plupart des gens présumeraient que le dernier jour de janvier, plus un mois, équivaut au dernier jour de février. Cela fonctionnera également sur un nombre négatif de mois. Preuve:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 
12
user417751

Il n'y a pas de moyen direct de le faire avec le datetime de Python.

Vérifiez le type relativedelta à python-dateutil . Il vous permet de spécifier un delta temporel en mois.

11
Akbar ibrahim

Utilisez simplement la méthode timinguple pour extraire les mois, ajoutez vos mois et créez un nouvel objet de date. S'il existe déjà une méthode pour cela, je ne la connais pas.

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

L'API est un peu maladroite, mais fonctionne à titre d'exemple. De toute évidence, cela ne fonctionnera évidemment pas dans les cas critiques comme le 2008-01-31 + 1 mois. :)

9
pi.

paquet Dateutil dispose de cette fonctionnalité. Mais sachez que ce sera naïf , comme d'autres l'ont déjà souligné.

8
zgoda

En utilisant Python bibliothèques standard, c'est-à-dire sans dateutil ou d'autres, et en résolvant le problème du "31 février":

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date

Essai:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))
8
David Ragazzi

J'ai un meilleur moyen de résoudre le problème du 31 février:

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

Je pense que cela fonctionne aussi avec des nombres négatifs (pour soustraire des mois), mais je n'ai pas encore beaucoup testé.

5
amoyafoss

La classe QDate de PyQt4 a une fonction addmonths.

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)
3
user213043

Que dis-tu de ça? Ne pas utiliser une autre bibliothèque (dateutil) ou timedelta? je me suis appuyé sur la réponse de vartec et je crois que cela fonctionne:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

J'ai essayé d'utiliser timedelta, mais comme il compte les jours, 365/2 ou 6*356/12 ne se traduit pas toujours par 6 mois, mais par 182 jours. par exemple.

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

Je pense que nous supposons généralement que 6 mois à partir d’un certain jour atterriront le même jour du mois mais 6 mois plus tard (c.-à-d. 2015-03-10 -> 2015-09-10, pas 2015-09-08)

J'espère que ça t'as aidé.

2
Babak K
import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(Tuple(t)))
2
ares

Modification de AddMonths () pour une utilisation dans Zope et gestion des numéros de jour non valides:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)
2
Jost

Voici un exemple qui permet à l'utilisateur de décider comment renvoyer une date où le jour est supérieur au nombre de jours du mois.

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        Elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)
1
Bruce Jakeway

étant donné que votre variable datetime est appelée date:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)
1
blacknight12321

Réponse modifiée de Johannes Wei dans le cas 1new_month = 121. Cela fonctionne parfaitement pour moi. Les mois peuvent être positifs ou négatifs.

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)
1
Xinhui Tang

Fonction générale pour obtenir la prochaine date après/avant x mois.

 à partir de la date d'importation de date/heure 
 
 def after_month (donnée le jour): 
 yyyy = int (((donnée le jour.année * 12 + donnée le jour le mois)) + mois )/12) 
 Mm = int (((donnée_date.année * 12 + donnée_date.mois) + mois)% 12) 
 
 Si mm == 0: 
 yyyy - = 1 
 mm = 12 
 renvoyer date_date.remplace (année = aaaa, mois = mm) 
 
 
 si __ = = "__main __": 
 aujourd’hui = date.aujourd’hui () 
 imprimer (aujourd’hui) 
 
 pour mm dans [-12, -1, 0, 1, 2, 12, 20]: 
 Next_date = after_month (aujourd'hui, mm) 
 Print (next_date) 
1
Nandlal Yadav

De cette réponse , voir parsedatetime . Exemple de code suit. Plus de détails: test unitaire avec de nombreux exemples de conversion YYYY-MM-DD en langage naturel , et apparent problèmes/bogues de conversion de parsedatetime .

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

Le code ci-dessus génère les éléments suivants à partir d’une machine MacOSX:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 
1
Johnny Utahh

Encore une autre solution - espérons que quelqu'un l'aimera:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

Cette solution ne fonctionne pas pendant les jours 29,30,31 pour tous les cas, une solution plus robuste est donc nécessaire (ce qui n’est plus aussi agréable :)):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")
1
Robert Lujo
import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __== '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))
1
tony diep

Utilisez le module python datetime pour ajouter un délai de six mois à datetime.today ().

http://docs.python.org/library/datetime.html

Vous devrez bien sûr résoudre le problème soulevé par Johannes Weiß - que voulez-vous par 6 mois?

0
Devin Jeanpierre

C'est ce que je suis venu avec. Il déplace le nombre correct de mois et d'années mais ignore les jours (ce qui était ce dont j'avais besoin dans ma situation).

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)
0
marshallpenguin

J'utilise cette fonction pour changer l'année et le mois mais garder le jour:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

Vous devriez écrire:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)
0
gt_rocker

Reprise d'une réponse antérieure par l'utilisateur417751. Peut-être pas de façon pythonique, mais cela prend en charge différentes durées de mois et années bissextiles. Dans ce cas, le 31 janvier 2012 + 1 mois = le 29 février 2012.

import datetime
import calendar

def add_mths(d, x):
    newday = d.day
    newmonth = (((d.month - 1) + x) % 12) + 1
    newyear  = d.year + (((d.month - 1) + x) // 12)
    if newday > calendar.mdays[newmonth]:
        newday = calendar.mdays[newmonth]
        if newyear % 4 == 0 and newmonth == 2:
            newday += 1
    return datetime.date(newyear, newmonth, newday)
0
Ireneusz

J'ai utilisé la méthode replace() et écris cette fonction récursive. la dt est un objet datetime.datetime:

def month_timedelta(dt, m):
    y = m // 12
    dm = m % 12
    if y == 0:
        if dt.month + m <= 12:
            return dt.replace(month = dt.month + m)
        else:
            dy = (dt.month + m) // 12
            ndt = dt.replace(year=dt.year + dy)
            return ndt.replace(month=(ndt.month + m) % 12)
    else:
        return month_timedelta(dt.replace(year=dt.year + y),dm)
0
Daniel MM. Kamani

Je sonne en retard, mais

découvrez le module Ken Reitz Maya,

https://github.com/kennethreitz/maya

quelque chose comme ceci peut vous aider, changez simplement les heures = 1 en jours = 1 ou années = 1

>>> from maya import MayaInterval

# Create an event that is one hour long, starting now.
>>> event_start = maya.now()
>>> event_end = event_start.add(hours=1)

>>> event = MayaInterval(start=event_start, end=event_end)
0
perfecto25

Une autre solution: calculer la somme des jours du mois pour le n prochain mois et ajouter le résultat à la date du jour.

import calendar
import datetime

def date_from_now(months):
    today = datetime.datetime.today()

    month = today.month
    year = today.year
    sum_days = 0

    for i in range(int(months)):
        month += 1

        if month == 13:
            month = 1
            year += 1

        sum_days += calendar.monthrange(year, month)[1]

    return datetime.date.today() + datetime.timedelta(sum_days)

print(date_from_now(12)) # if to day is 2017-01-01, output: 2019-01-01 
0
bii811

Une suggestion rapide est flèche

pip installer la flèche

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)
0
Diego Magalhães

Je pense qu'il serait plus prudent de faire quelque chose comme ceci au lieu d'ajouter manuellement des jours:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

newdate = addMonths(today, 6)
0
DataGreed

J'ai résolu ce problème comme ceci:

import calendar
from datetime import datetime
moths2add = 6
now = datetime.now()
current_year = now.year
current_month = now.month
#count days in months you want to add using calendar module
days = sum(
  [calendar.monthrange(current_year, elem)[1] for elem in range(current_month, current_month + moths)]
    )
print now + days
0
BabySnake