¿Cómo calculo la fecha de seis meses a partir de la fecha actual utilizando el módulo de Python datetime?

Estoy usando el módulo de Python datetime. Estoy buscando para calcular la fecha 6 meses a partir de la fecha actual. ¿Podría alguien ayudarme un poco haciendo esto?

La razón por la que quiero generar una fecha de 6 meses a partir de la fecha actual es para producir una fecha de revisión . Si el usuario ingresa datos en el sistema, tendrá una fecha de revisión de 6 meses a partir de la fecha en que ingresó los datos.

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

Encontré esta solución para ser buena. (Esto usa la extensión python-dateutil )

 from datetime import date from dateutil.relativedelta import relativedelta six_months = date.today() + relativedelta(months=+6) 

La ventaja de este enfoque es que resuelve los problemas con 28, 30, 31 días, etc. Esto resulta muy útil para manejar las reglas y los escenarios comerciales (por ejemplo, la generación de facturas, 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) 

Bueno, eso depende de lo que quieras decir en 6 meses a partir de la fecha actual.

  1. Utilizando meses naturales:

     (day, month, year) = (day, (month+6)%12, year+(month+6)/12) 
  2. Usando la definición de un banquero, 6 * 30:

     date += datetime.timedelta(6*30) 

Para el inicio del cálculo mes a mes:

 from datetime import timedelta from dateutil.relativedelta import relativedelta end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period) 

¿Qué quieres decir con ‘6 meses’. ¿Es 2009-02-13 + 6 meses == 2009-08-13 o es 2009-02-13 + 6 * 30 días?

 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' 

Más información sobre mx.DateTime

Esta solución funciona correctamente en diciembre, lo que no hace la mayoría de las respuestas en esta página. Primero debe cambiar los meses de la base 1 (es decir, Jan = 1) a la base 0 (es decir, Jan = 0) antes de usar el módulo (%) o la división entera (//); de lo contrario, noviembre (11) más 1 mes le da 12 , que al encontrar el rest (12% 12) da 0.

(Y no sugiera “(mes% 12) + 1” o Oct + 1 = diciembre!)

 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) 

Sin embargo … Esto no tiene en cuenta un problema como el 31 de enero + un mes. Así que volvemos a la OP. ¿Qué quiere decir con agregar un mes? Una solución es retroceder hasta llegar a un día válido, dado que la mayoría de las personas supondrían que el último día de enero, más un mes, es igual al último día de febrero. Esto también funcionará en números negativos de meses. Prueba:

 >>> 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)>>> 

No hay manera directa de hacerlo con la fecha y hora de Python.

Echa un vistazo a el tipo relativedelta en python-dateutil . Te permite especificar un delta de tiempo en meses.

Entonces, aquí hay un ejemplo de dateutil.relativedelta que encontré útil para iterar durante el año pasado, saltando un mes cada vez hasta la fecha actual:

 >>> 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 

Al igual que con las otras respuestas, debes averiguar a qué te refieres con "6 meses a partir de ahora". Si quiere decir "el día de hoy del mes en el mes, seis años en el futuro", esto sería:

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

Sé que esto fue por 6 meses, sin embargo, la respuesta se muestra en google para “agregar meses en python” si agrega un mes:

 import calendar date = datetime.date.today() //Or your date datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1]) 

esto contaría los días en el mes actual y los agregaría a la fecha actual, si utiliza 365/12, un anuncio de 1/12 de un año puede causar problemas por meses cortos / largos si realiza la iteración durante la fecha.

Con Python 3.x puedes hacerlo así:

 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 

pero necesitarás instalar el módulo python-dateutil :

 pip install python-dateutil 

Simplemente use el método de tiempo para extraer los meses, agregue sus meses y genere un nuevo objeto de fecha. Si ya existe un método para esto, no lo sé.

 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) 

La API es un poco torpe, pero funciona como un ejemplo. Obviamente, tampoco funcionará en casos de esquina como 2008-01-31 + 1 mes. 🙂

El paquete Dateutil tiene implementación de dicha funcionalidad. Pero ten en cuenta que esto será ingenuo , como ya han señalado otros.

Usando bibliotecas estándar de Python, es decir, sin dateutil u otros, y resolviendo el problema dateutil febrero’:

 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 

Pruebas:

 >>>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)) 

Tengo una mejor manera de resolver el problema ’31 de febrero’:

 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) 

Creo que también funciona con números negativos (para restar meses), pero no lo he probado mucho.

La clase QDate de PyQt4 tiene una función 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) 

Modificó los AddMonths () para usarlos en Zope y manejar números de días no válidos:

 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) 
 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))) 

¿Qué tal esto? ¿No dateutil usando otra biblioteca ( dateutil ) o timedelta ? Sobre la base de la respuesta de Vartec , hice esto y creo que funciona:

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

Intenté usar timedelta , pero como está contando los días, 365/2 o 6*356/12 365/2 no siempre se traduce a 6 meses, sino a 182 días. p.ej

 day = datetime.date(2015, 3, 10) print day >>> 2015-03-10 print (day + datetime.timedelta(6*365/12)) >>> 2015-09-08 

Creo que generalmente asumimos que 6 meses a partir de un día determinado aterrizarán el mismo día del mes pero 6 meses después (es decir, 2015-03-10 -> 2015-09-10 , no 2015-09-08 )

Espero que encuentres esto útil.

Resolví este problema así:

 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 
 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 __name__ == '__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)) 

Se modificó la respuesta de Johannes Wei en el caso 1new_month = 121. Esto funciona perfectamente para mí. Los meses pueden ser positivos o negativos.

 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) 

Otra solución más – espero que a alguien le guste:

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

Esta solución no funciona en los días 29, 30, 31 para todos los casos, por lo que se necesita una solución más robusta (que ya no es tan agradable :)):

 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") 

De esta respuesta , vea parsedatetime . Código de ejemplo que sigue. Más detalles: prueba de unidad con muchos ejemplos de conversión de lenguaje natural -> YYYY-MM-DD , y problemas / errores de conversión de parsedatatime aparentes.

 #!/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') 

El código anterior genera lo siguiente desde una máquina MacOSX:

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

Aquí hay un ejemplo que le permite al usuario decidir cómo devolver una fecha donde el día es mayor que la cantidad de días en el mes.

 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) 

Dado que su variable datetime se llama fecha:

 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) 

Función general para obtener la siguiente fecha después / antes de x meses.

 desde fecha de importación de fecha y hora

 def after_month (given_date, month):
     yyyy = int (((given_date.year * 12 + given_date.month) + month) / 12)
     mm = int (((given_date.year * 12 + given_date.month) + mes)% 12)

     si mm == 0:
         yyyy - = 1
         mm = 12
     return given_date.replace (año = aaaa, mes = mm)


 si __name__ == "__main__":
     hoy = fecha.today ()
     imprimir (hoy)

     para mm en [-12, -1, 0, 1, 2, 12, 20]:
         next_date = after_month (hoy, mm)
         imprimir (next_date)

Use el módulo datetime de python para agregar una fecha de seis meses a datetime.today ().

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

Por supuesto, tendrá que resolver el problema planteado por Johannes Weiss: ¿ qué quiere decir con 6 meses?

Esto es lo que se me ocurrió. Mueve la cantidad correcta de meses y años, pero ignora los días (que era lo que necesitaba en mi situación).

 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) 

Utilizo esta función para cambiar el año y el mes, pero mantengo el día:

 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 

Deberías escribir:

 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) 

Creo que sería más seguro hacer algo como esto en lugar de agregar días manualmente:

 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)