Objeto de fecha y hora de devolución del mes anterior

Resuelto Bialecki asked hace 14 años • 23 respuestas

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 ?

Bialecki avatar Aug 06 '10 21:08 Bialecki
Aceptado

Puede utilizar el dateutilmó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
amoe avatar Jan 22 '2013 13:01 amoe

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)
Cory avatar Aug 22 '2011 20:08 Cory

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])
Duncan avatar Aug 06 '2010 15:08 Duncan