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.
import datetime
print (datetime.date.today() + datetime.timedelta(6*365/12)).isoformat()
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)
Cela dépend de ce que vous entendez par 6 mois à compter de la date du jour.
En utilisant des mois naturels:
(day, month, year) = (day, (month+6)%12, year+(month+6)/12)
En utilisant la définition d'un banquier, 6 * 30:
date += datetime.timedelta(6*30)
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)
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
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
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.
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)
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)>>>
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.
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. :)
paquet Dateutil dispose de cette fonctionnalité. Mais sachez que ce sera naïf , comme d'autres l'ont déjà souligné.
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))
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é.
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)
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é.
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)))
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)
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)
é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)
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)
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)
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
$
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")
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))
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?
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)
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)
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)
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)
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)
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
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)
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)
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