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!


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.


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

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

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

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

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

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

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


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

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.


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')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.