data python do mês anterior

132

Estou tentando obter a data do mês anterior com python. Aqui está o que eu tentei:

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

No entanto, esse caminho é ruim por 2 motivos: primeiro ele retorna 20122 para fevereiro de 2012 (em vez de 201202) e, em segundo lugar, retorna 0 em vez de 12 em janeiro.

Eu resolvi esse problema no bash com

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

Eu acho que se o bash tem um caminho embutido para esse fim, o python, muito mais equipado, deve fornecer algo melhor do que forçar a escrita do próprio script para atingir esse objetivo. Claro que eu poderia fazer 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)

Não testei esse código e não quero usá-lo de qualquer maneira (a menos que não encontre outra maneira: /)

Obrigado pela ajuda!

philippe
fonte

Respostas:

300

As classes datetime e datetime.timedelta são suas amigas.

  1. encontre hoje.
  2. use isso para encontrar o primeiro dia deste mês.
  3. use timedelta para fazer backup de um único dia, até o último dia do mês anterior.
  4. imprima a sequência YYYYMM que você está procurando.

Como isso:

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

201202 é impresso.

bgporter
fonte
31
você poderia usar o .replace()método:datetime.utcnow().replace(day=1) - timedelta(days=1)
jfs 16/03/12
1
Legal! Perdi o método de substituição.
bgporter
Você também pode encadear a .replace()função. Faça uma vez para obter o último mês e, em seguida, faça novamente para obter o dia que você deseja. Primeiro: d = date.today() entãoone_month_ago = (d.replace(day=1) - timedelta(days=1)).replace(day=d.day)
Thane Plummer
@JFSebastian Você está certo - obrigado por apontar isso. Não parece haver uma linha elegante para isso, pois um "mês" não é um período de tempo constante. Você pode fazer algo feio importando calendare usando calendar.mdays[d.month-1]e mais feiúra em uma min()função no 2º replace, mas parece não-pitonico e não é responsável por casos extremos. Atualizei minha resposta abaixo usando try - exceptquais contas para todos os casos, embora eu odeie usar exceções como parte de um algoritmo.
21815 Thanh Plummer
veja a resposta de Ivan e adicione: min (date.today (). day, last_day_of_previous_month.day)
michel.iamit
70

Você deve usar o dateutil . Com isso, você pode usar o relativedelta, é uma versão aprimorada do 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
fonte
Não está funcionando no primeiro mês do ano: >>> IllegalMonthError: número do mês ruim -1; deve ser 1-12
mtoloo 16/01
@mtoloo Qual versão do dateutil? Não estou tendo esse problema, mas vou adicionar uma sintaxe alternativa
Dave Butler
1
Eu prefiro este porque, embora o @bgporter tenha uma solução muito boa, o dele não funciona tão bem para procurar no próximo mês.
Daniel F
3
@mtoloo Você provavelmente mistyped meses / mês
r_black
2
@r_black Sim Você está certo. Isso foi culpa minha. A solução fornecida aqui está correta e nenhuma verificação adicional é necessária para o primeiro mês do ano.
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

Ou:

from datetime import date, timedelta

prev = date.today().replace(day=1) - timedelta(days=1)
print prev.month
Ivan
fonte
parte da solução ... para encontrar o dia do mês passado, adicione algo como isto: day_previous_month = min (today.day, last_day_of_previous_month.day) para evitar exceder o número de dias.
Michel.iamit
9

Com base na resposta 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
fonte
5

É muito fácil e simples. Faça isso

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

Aqui está a saída: $ 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
fonte
4

Para alguém que chegou aqui e deseja obter o primeiro e o último dia do mês 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)

Resultado:

First day of prev month: 2019-02-01
Last day of prev month: 2019-02-28
Robin Carlo Catacutan
fonte
Se você deseja obter o início eo fim de um mês (e mais), ter um olhar para o Calendarmódulo: stackabuse.com/introduction-to-the-python-calendar-module
toast38coza
Se queremos começar e terminar o segundo mês anterior?
gamer
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
fonte
Quebra em 31 de março
Mike
1

Apenas por diversão, uma resposta matemática pura usando divmod. Bastante ineficiente devido à multiplicação, poderia fazer também uma verificação simples do número de meses (se for igual a 12, aumentar ano, 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
fonte
1

Com a biblioteca muito completa do Pêndulo , temos o subtractmétodo (e não "subStract"):

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

Vemos que ele lida com anos de salto.

O equivalente inverso é add.

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

Ehvince
fonte
0

Com base no comentário de @JF Sebastian, você pode encadear a replace()função para voltar um "mês". Como um mês não é um período de tempo constante, esta solução tenta voltar à mesma data do mês anterior, o que obviamente não funciona em todos os meses. Nesse caso, esse algoritmo é padronizado para o último dia do mês 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))

Resultado:

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

Se você deseja examinar as letras ASCII em um arquivo do tipo EXE em um ambiente LINUX / UNIX, tente "od -c 'filename' | more"

Você provavelmente receberá muitos itens irreconhecíveis, mas todos serão apresentados e as representações HEX serão exibidas, e os caracteres equivalentes a ASCII (se apropriado) seguirão a linha de códigos hexadecimais. Experimente em um pedaço de código compilado que você conhece. Você pode ver coisas nele que reconhece.

Rick
fonte
Você pode editar isso para explicar como responde à pergunta.
AdrianHHH
0

Existe uma biblioteca de alto nível dateparserque pode determinar a data anterior dada a linguagem natural e retornar o Python correspondentedatetime objeto

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