Objeto de fecha y hora de devolución del mes anterior
Si tan solo timedelta tuviera un argumento de mes en su constructor. Entonces, ¿cuál es la forma más sencilla de hacer esto?
EDITAR: No estaba pensando demasiado en esto como se señala a continuación. Realmente lo que quería era cualquier día del último mes porque eventualmente solo tomaré el año y el mes. Entonces, dado un objeto de fecha y hora, ¿cuál es la forma más sencilla de devolver cualquier objeto de fecha y hora que caiga en el mes anterior ?
Puede utilizar el dateutil
módulo de terceros (entrada PyPI aquí ).
import datetime
import dateutil.relativedelta
d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1)
print d2
producción:
2013-02-28 00:00:00
Después de editar la pregunta original a "cualquier objeto de fecha y hora del mes anterior", puede hacerlo con bastante facilidad restando 1 día del primero del mes.
from datetime import datetime, timedelta
def a_day_in_previous_month(dt):
return dt.replace(day=1) - timedelta(days=1)
Prueba esto:
def monthdelta(date, delta):
m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
if not m: m = 12
d = min(date.day, [31,
29 if y%4==0 and (not y%100==0 or y%400 == 0) else 28,
31,30,31,30,31,31,30,31,30,31][m-1])
return date.replace(day=d,month=m, year=y)
>>> for m in range(-12, 12):
print(monthdelta(datetime.now(), m))
2009-08-06 16:12:27.823000
2009-09-06 16:12:27.855000
2009-10-06 16:12:27.870000
2009-11-06 16:12:27.870000
2009-12-06 16:12:27.870000
2010-01-06 16:12:27.870000
2010-02-06 16:12:27.870000
2010-03-06 16:12:27.886000
2010-04-06 16:12:27.886000
2010-05-06 16:12:27.886000
2010-06-06 16:12:27.886000
2010-07-06 16:12:27.886000
2010-08-06 16:12:27.901000
2010-09-06 16:12:27.901000
2010-10-06 16:12:27.901000
2010-11-06 16:12:27.901000
2010-12-06 16:12:27.901000
2011-01-06 16:12:27.917000
2011-02-06 16:12:27.917000
2011-03-06 16:12:27.917000
2011-04-06 16:12:27.917000
2011-05-06 16:12:27.917000
2011-06-06 16:12:27.933000
2011-07-06 16:12:27.933000
>>> monthdelta(datetime(2010,3,30), -1)
datetime.datetime(2010, 2, 28, 0, 0)
>>> monthdelta(datetime(2008,3,30), -1)
datetime.datetime(2008, 2, 29, 0, 0)
Editar Corregido para manejar el día también.
Editar Vea también la respuesta del desconcierto que señala un cálculo más simple para d
:
d = min(date.day, calendar.monthrange(y, m)[1])