semana - ¿Cómo calculo la fecha seis meses a partir de la fecha actual utilizando el módulo de Python datetime?
obtener el dia de la semana en python (30)
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.
¿Qué quiere 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
¿Qué tal esto? ¿No dateutil
usando otra biblioteca ( dateutil
) o timedelta
? Sobre la de la respuesta de , 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.
Bueno, eso depende de lo que quieras decir en 6 meses a partir de la fecha actual.
Utilizando meses naturales:
(day, month, year) = (day, (month+6)%12, year+(month+6)/12)
Usando la definición de un banquero, 6 * 30:
date += datetime.timedelta(6*30)
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
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)
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)
De esta respuesta , vea parsedatetime . Código de ejemplo 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
$
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)
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, enero = 1) a la base 0 (es decir, enero = 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 resto (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 explica 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)>>>
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)
Función general para obtener la próxima fecha después de x meses.
from datetime import date 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) + month)%12) if mm == 0: yyyy -= 1 mm = 12 return given_date.replace(year=yyyy, month=mm) if __name__ == "__main__": today = date.today() print(today) for mm in [-12, -1, 0, 1, 2, 12, 20 ]: next_date = after_month(today, mm) print(next_date)
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)
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.
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")
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)
Por lo tanto, aquí hay un ejemplo de dateutil.relativedelta
que encontré útil para iterar durante el año pasado, omitiendo 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 "dentro de 6 meses". 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)
Redacción de una respuesta anterior por el usuario 417751. Tal vez no sea de una manera tan pitónica, pero se ocupa de diferentes meses y años bisiestos. En este caso 31 de enero de 2012 + 1 mes = 29 de febrero de 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)
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
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 ocasionar problemas durante meses cortos / largos si realiza iteraciones durante la fecha.
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)
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, 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. :)
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.
Usando las 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))
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?
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)
El paquete de Dateutil tiene implementación de dicha funcionalidad. Pero ten en cuenta que esto será ingenuo , como ya han señalado otros.
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))
import datetime
print (datetime.date.today() + datetime.timedelta(6*365/12)).isoformat()
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)))