Seite 1 von 1

Datumsberechnung

Verfasst: Freitag 16. März 2018, 23:14
von reneschmidt
Hallo zusammen,

irgendwie kommt ich an folgendem Punkt nicht weiter:
Ich habe ein Datum (z.B. 15.06.2018) und davon muss ich jetzt z.B. 36 oder 40 Monate zurück gehen.
Hat jemand einen Vorschlag, wie man das am einfachsten in Python realisieren kann?

Vielen Dank im Voraus.

Re: Datumsberechnung

Verfasst: Freitag 16. März 2018, 23:42
von __deets__
Mit dem datetime Modul und seinen Klassen wie zB timedelta,das so etwas kann.

Re: Datumsberechnung

Verfasst: Montag 19. März 2018, 10:07
von sebastian0202
Hallo,


ich würde obige Aufgabe so erledigen:
Die Lösung fühlt sich aber nicht gut an.
Darf man Funktionen in Funktionen definieren?

Code: Alles auswählen

from datetime import datetime, timedelta
from itertools import count

def subtract_month(date, months=1):
    def february(year):
        return 29 if year%4==0 and not year%400==0 else 28
        
    def days_per_month(date):
        return {"1":31, "2":february(date.year), "3":31, "4":30, "5":31,
                "6":30, "7":31, "8":31, "9":30, "10":31, "11":30, "12":31}

    for i in count(1):
        if i > months:
            break
        period = days_per_month(date)[str(date.month)]
        date = date - timedelta(days=period)
    return date


if __name__ == '__main__':
    date = datetime(2020,3,29,6,30)

    for i in range(1,13):
        print subtract_month(date, i)
'''
2020-02-27 06:30:00
2020-01-29 06:30:00
2019-12-29 06:30:00
2019-11-28 06:30:00
2019-10-29 06:30:00
2019-09-28 06:30:00
2019-08-29 06:30:00
2019-07-29 06:30:00
2019-06-28 06:30:00
2019-05-29 06:30:00
2019-04-28 06:30:00
2019-03-29 06:30:00
'''

Re: Datumsberechnung

Verfasst: Montag 19. März 2018, 11:10
von Sirius3
@sebastian0202: Deine Schaltjahrberechnung ist falsch. Ansonsten gibt es das alles schon im calendar-Modul. Ein `count` mit einem break, falls der Wert größer als eine bestimmte Grenze wird, ist eigentlich ein `range`. Warum benutzt Du für die Monatsnummer einen String? Wäre es nicht einfacher, Monat und Jahr separat auszurechnen und den Tag aus dem ursprünglichen Datum zu nehmen?

Code: Alles auswählen

>>> import datetime
>>> date = datetime.datetime.now()
>>> y, m = divmod(date.year*12+date.month - 21, 12)
>>> date.replace(year=y, month=m)
datetime.datetime(2016, 6, 19, 11, 11, 48, 413895)

Re: Datumsberechnung

Verfasst: Montag 19. März 2018, 16:08
von narpfel
@Sirius3: Man kann den Tag nicht aus dem ursprünglichen Datum nehmen, weil nicht alle Tage in allen Monaten existieren:

Code: Alles auswählen

In [18]: date = datetime.datetime(2018, 3, 31)

In [19]: date.replace(month=2)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-19-6ef8040186bb> in <module>()
----> 1 date.replace(month=2)

ValueError: day is out of range for month
@reneschmidt: Ob man jetzt mit `replace` die Jahre und Monate ändert oder `timedelta`s (bzw. Tage) aufsummiert, hängt so ein bisschen davon ab, was „ein Monat“ für dich ist. Was ist ein Monat vor dem 29. März? Der 28./29. Februar? 31 Tage früher? Vier Wochen früher? Was ist mit Sommer- und Winterzeit? Schaltsekunden? Diese Fragen müsstest du (für dich) beantworten.

Re: Datumsberechnung

Verfasst: Dienstag 20. März 2018, 09:47
von sebastian0202
Ja, die Schaltjahrberechnung ist falsch. Habe die Sache mit den 100 Jahren unter den Tisch fallen lassen.
Hab jetzt mit 'Calendar' einen kürzeren Code. Der wird aber für viele Durchläufe sicher uneffizient sein.

Code: Alles auswählen

from calendar import monthrange
from datetime import datetime, timedelta
...
def schaltjahr(jahr):
    return 28 if jahr%100==0 and not jahr%400==0 else (29 if jahr%4==0 else 28)
...
def subtract_month(date, months=1):
    for _ in range(months):
        date -= timedelta (days=monthrange(date.year,date.month)[1])
    return date

if __name__ == '__main__':
    date = datetime(2018,03,31)
    print subtract_month(date, 37)
'''
2015-02-28 00:00:00
'''

Re: Datumsberechnung

Verfasst: Dienstag 20. März 2018, 19:56
von snafu
Es gibt schon calendar.isleap() zur Ermittlung eines Schaltjahrs...