196 Stimmen

Jahr/Monat/Tag in Tag des Jahres in Python umrechnen

Ich benutze die datetime Modul, d.h.:

>>> import datetime
>>> today = datetime.datetime.now()
>>> print(today)
2009-03-06 13:24:58.857946

und ich möchte den Tag des Jahres berechnen, der die Schaltjahre berücksichtigt. z.B. ist heute (6. März 2009) der 65. Tag des Jahres 2009.

Ich sehe zwei Möglichkeiten:

  1. Erstellen einer number_of_days_in_month = [31, 28, ...] Array, entscheiden Sie, ob es sich um ein Schaltjahr handelt, und addieren Sie die Tage manuell.

  2. Utilice datetime.timedelta um eine Vermutung anzustellen und dann binär nach dem richtigen Tag des Jahres zu suchen:

    >>> import datetime
    >>> YEAR = 2009
    >>> DAY_OF_YEAR = 62
    >>> d = datetime.date(YEAR, 1, 1) + datetime.timedelta(DAY_OF_YEAR - 1)

Diese beiden fühlen sich ziemlich klobig & Ich habe ein Bauchgefühl, dass es eine mehr "Pythonic" Weg zur Berechnung der Tag des Jahres. Irgendwelche Ideen/Vorschläge?

370voto

DzinX Punkte 51124

Utilisez datetime.timetuple() zur Umwandlung Ihrer datetime Objekt zu einem time.struct_time Objekt erhalten dann seine tm_yday Eigentum:

from datetime import datetime
day_of_year = datetime.now().timetuple().tm_yday  # returns 1 for January 1st

70voto

Paolo Bergantino Punkte 465120

Sie könnten verwenden strftime mit einer %j Formatzeichenkette :

>>> import datetime
>>> today = datetime.datetime.now()
>>> today.strftime('%j')
'065'

aber wenn Sie Vergleiche oder Berechnungen mit dieser Zahl durchführen wollen, müssen Sie sie in int() denn strftime() gibt eine Zeichenkette zurück. Wenn das der Fall ist, ist es besser, wenn Sie DzinX's Antwort.

17voto

Dave X Punkte 3965

DZinX's Antwort ist eine gute Antwort auf diese Frage. Ich habe diese Frage gefunden und verwendet DZinX's Antwort auf der Suche nach der Umkehrfunktion: Konvertieren von Daten mit dem julianischen Tag des Jahres in die Datumszeiten.

Ich habe festgestellt, dass dies funktioniert:

import datetime
datetime.datetime.strptime('1936-077T13:14:15','%Y-%jT%H:%M:%S')

>>>> datetime.datetime(1936, 3, 17, 13, 14, 15)

datetime.datetime.strptime('1936-077T13:14:15','%Y-%jT%H:%M:%S').timetuple().tm_yday

>>>> 77

Oder numerisch:

import datetime
year,julian = [1936,77]
datetime.datetime(year, 1, 1)+datetime.timedelta(days=julian -1)

>>>> datetime.datetime(1936, 3, 17, 0, 0)

Oder mit gebrochenen 1-basierten Datumsangaben, die in einigen Bereichen beliebt sind:

jdate_frac = (datetime.datetime(1936, 3, 17, 13, 14, 15)-datetime.datetime(1936, 1, 1)).total_seconds()/86400+1
display(jdate_frac)

>>>> 77.5515625

year,julian = [1936,jdate_frac]
display(datetime.datetime(year, 1, 1)+datetime.timedelta(days=julian -1))

>>>> datetime.datetime(1936, 3, 17, 13, 14, 15)

Ich bin mir nicht sicher, wie die Etikette hier aussieht, aber ich dachte, ein Hinweis auf die umgekehrte Funktion könnte für andere wie mich nützlich sein.

12voto

Barry Andersen Punkte 427

Wenn Sie einen Grund haben, die Verwendung des datetime Modul, dann werden diese Funktionen funktionieren.

def is_leap_year(year):
    """ if year is a leap year return True
        else return False """
    if year % 100 == 0:
        return year % 400 == 0
    return year % 4 == 0

def doy(Y,M,D):
    """ given year, month, day return day of year
        Astronomical Algorithms, Jean Meeus, 2d ed, 1998, chap 7 """
    if is_leap_year(Y):
        K = 1
    else:
        K = 2
    N = int((275 * M) / 9.0) - K * int((M + 9) / 12.0) + D - 30
    return N

def ymd(Y,N):
    """ given year = Y and day of year = N, return year, month, day
        Astronomical Algorithms, Jean Meeus, 2d ed, 1998, chap 7 """    
    if is_leap_year(Y):
        K = 1
    else:
        K = 2
    M = int((9 * (K + N)) / 275.0 + 0.98)
    if N < 32:
        M = 1
    D = N - int((275 * M) / 9.0) + K * int((M + 9) / 12.0) + 30
    return Y, M, D

9voto

omikron Punkte 2495

Ich möchte die Leistung der verschiedenen Ansätze, auf Python 3.4, Linux x64 präsentieren. Auszug aus dem Line Profiler:

      Line #      Hits         Time  Per Hit   % Time  Line Contents
      ==============================================================
         (...)
         823      1508        11334      7.5     41.6          yday = int(period_end.strftime('%j'))
         824      1508         2492      1.7      9.1          yday = period_end.toordinal() - date(period_end.year, 1, 1).toordinal() + 1
         825      1508         1852      1.2      6.8          yday = (period_end - date(period_end.year, 1, 1)).days + 1
         826      1508         5078      3.4     18.6          yday = period_end.timetuple().tm_yday
         (...)

Am effizientesten ist also

yday = (period_end - date(period_end.year, 1, 1)).days + 1

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X