fecha de pitón del mes anterior

132

Estoy tratando de obtener la fecha del mes anterior con python. Esto es lo que he intentado:

str( time.strftime('%Y') ) + str( int(time.strftime('%m'))-1 )

Sin embargo, de esta manera es malo por 2 razones: primero devuelve 20122 para febrero de 2012 (en lugar de 201202) y, en segundo lugar, devolverá 0 en lugar de 12 en enero.

He resuelto este problema en bash con

echo $(date -d"3 month ago" "+%G%m%d")

Creo que si bash tiene una forma integrada para este propósito, entonces python, mucho más equipado, debería proporcionar algo mejor que forzar la escritura del propio script para lograr este objetivo. Por supuesto que podría hacer algo como:

if int(time.strftime('%m')) == 1:
    return '12'
else:
    if int(time.strftime('%m')) < 10:
        return '0'+str(time.strftime('%m')-1)
    else:
        return str(time.strftime('%m') -1)

No he probado este código y no quiero usarlo de todos modos (a menos que no pueda encontrar otra forma: /)

¡Gracias por tu ayuda!

philippe
fuente

Respuestas:

300

datetime y las clases datetime.timedelta son tu amigo.

  1. encontrar hoy
  2. utilízalo para encontrar el primer día de este mes.
  3. use timedelta para hacer una copia de seguridad de un solo día, hasta el último día del mes anterior.
  4. imprime la cadena AAAAMM que estás buscando.

Me gusta esto:

 import datetime
 today = datetime.date.today()
 first = today.replace(day=1)
 lastMonth = first - datetime.timedelta(days=1)
 print(lastMonth.strftime("%Y%m"))

201202 está impreso.

bgporter
fuente
31
puede usar el .replace()método:datetime.utcnow().replace(day=1) - timedelta(days=1)
jfs
1
¡Frio! Perdí el método de reemplazo.
bgporter
También puedes encadenar la .replace()función. Hágalo una vez para obtener el último mes, luego hágalo nuevamente para obtener el día que desea. Primero: d = date.today() luegoone_month_ago = (d.replace(day=1) - timedelta(days=1)).replace(day=d.day)
Thane Plummer
@JFSebastian Tienes razón, gracias por señalarlo. No parece haber una frase elegante para esto, ya que un "mes" no es un período de tiempo constante. Puedes hacer algo feo importando calendary usando calendar.mdays[d.month-1]y más fealdad en una min()función en la segunda replace, pero parece poco pitón y no tiene en cuenta los casos de esquina. He actualizado mi respuesta a continuación usando try - exceptqué cuentas para todos los casos, aunque odio usar excepciones como parte de un algoritmo.
Thane Plummer
vea la respuesta de Ivan y agregue: min (date.today (). day, last_day_of_previous_month.day)
michel.iamit
70

Deberías usar dateutil . Con eso, puedes usar relativedelta, es una versión mejorada de timedelta.

>>> import datetime 
>>> import dateutil.relativedelta
>>> now = datetime.datetime.now()
>>> print now
2012-03-15 12:33:04.281248
>>> print now + dateutil.relativedelta.relativedelta(months=-1)
2012-02-15 12:33:04.281248
Dave Butler
fuente
No funciona durante el primer mes del año: >>> IllegalMonthError: mes malo número -1; debe ser 1-12
mtoloo
@mtoloo ¿Qué versión de dateutil? No tengo ese problema, pero agregaré una sintaxis alternativa
Dave Butler el
1
Prefiero esta porque si bien @bgporter tiene una solución muy buena, la suya no funciona tan bien para buscar el próximo mes.
Daniel F
3
@mtoloo Probablemente has escrito mal mes / mes
r_black
2
@r_black Sí, tienes razón. Eso fue mi culpa. La solución dada aquí es correcta y no se necesita ninguna otra verificación para el primer mes del año.
mtoloo
45
from datetime import date, timedelta

first_day_of_current_month = date.today().replace(day=1)
last_day_of_previous_month = first_day_of_current_month - timedelta(days=1)

print "Previous month:", last_day_of_previous_month.month

O:

from datetime import date, timedelta

prev = date.today().replace(day=1) - timedelta(days=1)
print prev.month
Ivan
fuente
parte de la solución ... para encontrar el día del mes pasado, agregue algo como esto: day_previous_month = min (today.day, last_day_of_previous_month.day) para evitar exceder el número de días.
michel.iamit
9

Sobre la base de la respuesta de bgporter .

def prev_month_range(when = None): 
    """Return (previous month's start date, previous month's end date)."""
    if not when:
        # Default to today.
        when = datetime.datetime.today()
    # Find previous month: https://stackoverflow.com/a/9725093/564514
    # Find today.
    first = datetime.date(day=1, month=when.month, year=when.year)
    # Use that to find the first day of this month.
    prev_month_end = first - datetime.timedelta(days=1)
    prev_month_start = datetime.date(day=1, month= prev_month_end.month, year= prev_month_end.year)
    # Return previous month's start and end dates in YY-MM-DD format.
    return (prev_month_start.strftime('%Y-%m-%d'), prev_month_end.strftime('%Y-%m-%d'))
paragbaxi
fuente
5

Es muy fácil y sencillo. Hacer esto

from dateutil.relativedelta import relativedelta
from datetime import datetime

today_date = datetime.today()
print "todays date time: %s" %today_date

one_month_ago = today_date - relativedelta(months=1)
print "one month ago date time: %s" % one_month_ago
print "one month ago date: %s" % one_month_ago.date()

Aquí está el resultado: $ python2.7 main.py

todays date time: 2016-09-06 02:13:01.937121
one month ago date time: 2016-08-06 02:13:01.937121
one month ago date: 2016-08-06
Mahfuz
fuente
4

Para alguien que llegó aquí y busca obtener el primer y el último día del mes anterior:

from datetime import date, timedelta

last_day_of_prev_month = date.today().replace(day=1) - timedelta(days=1)

start_day_of_prev_month = date.today().replace(day=1) - timedelta(days=last_day_of_prev_month.day)

# For printing results
print("First day of prev month:", start_day_of_prev_month)
print("Last day of prev month:", last_day_of_prev_month)

Salida:

First day of prev month: 2019-02-01
Last day of prev month: 2019-02-28
Robin Carlo Catacutan
fuente
Si desea comenzar y finalizar un mes (y más), eche un vistazo al Calendarmódulo: stackabuse.com/introduction-to-the-python-calendar-module
toast38coza
Si queremos comenzar y finalizar el segundo mes anterior?
jugador
3
def prev_month(date=datetime.datetime.today()):
    if date.month == 1:
        return date.replace(month=12,year=date.year-1)
    else:
        try:
            return date.replace(month=date.month-1)
        except ValueError:
            return prev_month(date=date.replace(day=date.day-1))
Steve
fuente
Saltos el 31 de marzo
Mike
1

Solo por diversión, una respuesta matemática pura usando divmod. Bastante ineficiente debido a la multiplicación, podría ser igual de simple verificar el número de meses (si es igual a 12, aumentar año, etc.)

year = today.year
month = today.month

nm = list(divmod(year * 12 + month + 1, 12))
if nm[1] == 0:
    nm[1] = 12
    nm[0] -= 1
pm = list(divmod(year * 12 + month - 1, 12))
if pm[1] == 0:
    pm[1] = 12
    pm[0] -= 1

next_month = nm
previous_month = pm
Tiberiu Ichim
fuente
1

Con la biblioteca muy completa Pendulum , tenemos el subtractmétodo (y no "subStract"):

import pendulum
today = pendulum.datetime.today()  # 2020, january
lastmonth = today.subtract(months=1)
lastmonth.strftime('%Y%m')
# '201912'

Vemos que maneja años saltando.

El equivalente inverso es add.

https://pendulum.eustace.io/docs/#addition-and-subtraction

Ehvince
fuente
0

A partir del comentario de @JF Sebastian, puede encadenar la replace()función para retroceder un "mes". Dado que un mes no es un período de tiempo constante, esta solución intenta volver a la misma fecha del mes anterior, que por supuesto no funciona en todos los meses. En tal caso, este algoritmo se predetermina al último día del mes anterior.

from datetime import datetime, timedelta

d = datetime(2012, 3, 31) # A problem date as an example

# last day of last month
one_month_ago = (d.replace(day=1) - timedelta(days=1))
try:
    # try to go back to same day last month
    one_month_ago = one_month_ago.replace(day=d.day)
except ValueError:
    pass
print("one_month_ago: {0}".format(one_month_ago))

Salida:

one_month_ago: 2012-02-29 00:00:00
Thane Plummer
fuente
0

Si desea ver las letras ASCII en un archivo de tipo EXE en un entorno LINUX / UNIX, intente "od -c 'filename' | more"

Probablemente obtendrá muchos elementos irreconocibles, pero todos se presentarán, y se mostrarán las representaciones HEX, y los caracteres equivalentes ASCII (si corresponde) seguirán la línea de códigos hexadecimales. Pruébelo en un código compilado que conozca. Puede ver cosas que reconoce.

Almiar
fuente
¿Puedes editar esto para explicar cómo responde la pregunta?
AdrianHHH
0

Hay una biblioteca de alto nivel dateparserque puede determinar la fecha pasada dado el lenguaje natural y devolver el datetimeobjeto Python correspondiente

from dateparser import parse
parse('4 months ago')
wesinat0r
fuente