Python-Datum des Vormonats


131

Ich versuche mit Python das Datum des Vormonats zu ermitteln. Folgendes habe ich versucht:

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

Dieser Weg ist jedoch aus zwei Gründen schlecht: Erstens wird 20122 für den Februar 2012 (anstelle von 201202) zurückgegeben, und zweitens wird im Januar 0 statt 12 zurückgegeben.

Ich habe dieses Problem in Bash mit gelöst

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

Ich denke, wenn bash eine eingebaute Methode für diesen Zweck hat, sollte Python, viel besser ausgestattet, etwas Besseres bieten, als das Schreiben eines eigenen Skripts zu erzwingen, um dieses Ziel zu erreichen. Natürlich könnte ich so etwas machen wie:

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)

Ich habe diesen Code nicht getestet und möchte ihn trotzdem nicht verwenden (es sei denn, ich finde keinen anderen Weg: /)

Danke für Ihre Hilfe!


Antworten:


299

datetime und die datetime.timedelta-Klassen sind dein Freund.

  1. heute finden.
  2. Verwenden Sie dies, um den ersten Tag dieses Monats zu finden.
  3. Verwenden Sie timedelta, um einen einzelnen Tag bis zum letzten Tag des Vormonats zu sichern.
  4. Drucken Sie die gesuchte Zeichenfolge JJJJMM.

So was:

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

201202 wird gedruckt.


31
Sie könnten .replace()Methode verwenden:datetime.utcnow().replace(day=1) - timedelta(days=1)
JFS

1
Cool! Ich habe die Ersetzungsmethode verpasst.
Bgporter

Sie können die .replace()Funktion auch verketten . Tun Sie es einmal, um den letzten Monat zu erhalten, und wiederholen Sie es dann erneut, um den gewünschten Tag zu erhalten. Zuerst: d = date.today() dannone_month_ago = (d.replace(day=1) - timedelta(days=1)).replace(day=d.day)
Thane Plummer

@JFSebastian Sie haben Recht - danke, dass Sie darauf hingewiesen haben. Es scheint keinen eleganten Einzeiler dafür zu geben, da ein "Monat" kein konstanter Zeitraum ist. Sie können etwas Hässliches tun, indem Sie eine Funktion im 2. importieren calendarund verwenden calendar.mdays[d.month-1]und mehr Hässlichkeit in einer min()Funktion replace, aber sie scheint nicht pythonisch zu sein und berücksichtigt keine Eckfälle. Ich habe meine Antwort unten mit try - exceptden Konten für alle Fälle aktualisiert , obwohl ich es hasse, Ausnahmen als Teil eines Algorithmus zu verwenden.
Thane Plummer

Sehen Sie sich die Antwort von Ivan an und fügen Sie hinzu: min (date.today (). day, last_day_of_previous_month.day)
michel.iamit

69

Sie sollten Dateutil verwenden . Damit können Sie relativedelta verwenden, eine verbesserte Version von 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

Es funktioniert nicht für den ersten Monat des Jahres: >>> IllegalMonthError: schlechte Monatsnummer -1; muss 1-12 sein
mtoloo

@mtoloo Welche Version von dateutil? Ich habe dieses Problem nicht, aber ich werde eine alternative Syntax hinzufügen
Dave Butler

1
Ich bevorzuge diese, weil @bgporter zwar eine sehr gute Lösung hat, seine aber nicht so gut funktioniert, um im nächsten Monat nachzuschlagen.
Daniel F

3
@mtoloo Sie haben wahrscheinlich Monate / Monat
falsch geschrieben

2
@r_black Ja Du hast recht. Das war meine Schuld. Die hier angegebene Lösung ist korrekt und für den ersten Monat des Jahres ist keine weitere Überprüfung erforderlich.
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

Oder:

from datetime import date, timedelta

prev = date.today().replace(day=1) - timedelta(days=1)
print prev.month

Teil der Lösung ... um den Tag des letzten Monats zu ermitteln, fügen Sie Folgendes hinzu: day_previous_month = min (today.day, last_day_of_previous_month.day), um zu vermeiden, dass die Anzahl der Tage überschritten wird.
michel.iamit

9

Aufbauend auf der Antwort von 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

Es ist sehr einfach und unkompliziert. Mach das

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

Hier ist die Ausgabe: $ 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

Für jemanden, der hierher gekommen ist und sowohl den ersten als auch den letzten Tag des Vormonats haben möchte:

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)

Ausgabe:

First day of prev month: 2019-02-01
Last day of prev month: 2019-02-28

Wenn Sie den Anfang und das Ende eines Monats (und mehr) erhalten möchten, schauen Sie sich das CalendarModul an: stackabuse.com/introduction-to-the-python-calendar-module
toast38coza

Wenn wir wollen, dass der 2. Vormonat beginnt und endet?
Spieler

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

Pausen am 31. März
Mike

1

Nur zum Spaß eine reine mathematische Antwort mit divmod. Aufgrund der Multiplikation ziemlich unzulänglich, könnte genauso gut eine einfache Überprüfung der Anzahl der Monate durchgeführt werden (wenn gleich 12, Jahr erhöhen usw.)

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

1

Mit dem Pendel sehr kompletten Bibliothek haben wir das subtractVerfahren (und nicht „subtrahieren“):

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

Wir sehen, dass es Sprungjahre bewältigt.

Das umgekehrte Äquivalent ist add.

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


0

Aufbauend auf dem Kommentar von @JF Sebastian können Sie die replace()Funktion verketten, um einen "Monat" zurück zu gehen. Da ein Monat kein konstanter Zeitraum ist, versucht diese Lösung, zum gleichen Datum des Vormonats zurückzukehren, was natürlich nicht für alle Monate funktioniert. In diesem Fall wird standardmäßig der letzte Tag des Vormonats verwendet.

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

Ausgabe:

one_month_ago: 2012-02-29 00:00:00

0

Wenn Sie die ASCII-Buchstaben in einer EXE-Datei in einer LINUX / UNIX-Umgebung anzeigen möchten, versuchen Sie "od -c 'Dateiname' | more".

Sie werden wahrscheinlich viele nicht erkennbare Elemente erhalten, aber alle werden angezeigt, und die HEX-Darstellungen werden angezeigt, und die ASCII-äquivalenten Zeichen (falls zutreffend) folgen der Zeile der Hex-Codes. Probieren Sie es mit einem kompilierten Code aus, den Sie kennen. Sie könnten Dinge darin sehen, die Sie erkennen.


Können Sie dies bitte bearbeiten , um zu erklären, wie es die Frage beantwortet?
AdrianHHH

0

Es gibt eine Bibliothek auf hoher Ebene dateparser, die das vergangene Datum in natürlicher Sprache bestimmen und das entsprechende Python- datetimeObjekt zurückgeben kann

from dateparser import parse
parse('4 months ago')
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.