Konvertieren Sie Jahr / Monat / Tag in Tag des Jahres in Python

127

Ich verwende das Python- Datum / Uhrzeit- Modul, dh:

>>> 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 für Schaltjahre empfindlich ist. Beispiel: Heute (6. März 2009) ist der 65. Tag des Jahres 2009. Hier ist der webbasierte DateTime-Rechner .

Wie auch immer, ich sehe zwei Möglichkeiten:

A. Erstellen Sie ein Array "number_of_days_in_month" = [31, 28, ...], entscheiden Sie, ob es sich um ein Schaltjahr handelt, und fassen Sie die Tage manuell zusammen.

B. Verwenden Sie datetime.timedeltadiese Option , um eine Vermutung anzustellen und anschließend binär nach dem richtigen Tag im Jahr 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 an und ich habe das Gefühl, dass es eine "pythonischere" Methode gibt, den Tag des Jahres zu berechnen. Irgendwelche Ideen / Vorschläge?

Pete
quelle

Antworten:

254

Es gibt eine sehr einfache Lösung:

from datetime import datetime
day_of_year = datetime.now().timetuple().tm_yday
DzinX
quelle
13
Eine sehr kleine und wohl pedantische Ergänzung, die jedoch date.today()eher verwendet als datetime.now()funktioniert und die Art der Operation ein bisschen mehr betont.
Jeremy
5
Besser noch: time.localtime().tm_yday Es ist nicht erforderlich, eine Datums- / Uhrzeitangabe in ein Zeitplättchen umzuwandeln, da localtime () dies ergibt.
Mike Ellis
14
@MikeEllis Diese Lösung zeigt jedoch, was zu tun ist, wenn die Datums- und Uhrzeitangabe nicht der heutigen entspricht.
Gerrit
2
Hinweis: Dies beginnt um 1
Mehdi Nellen
1
Was ist, wenn ich das Gegenteil tun möchte? Ich habe die Nummer "26. Tag des Jahres 2020" und möchte, dass sie in ein Datum "26-01-2020" umgewandelt wird.
Sankar
43

Könnten Sie nicht verwenden strftime?

>>> import datetime
>>> today = datetime.datetime.now()
>>> print today
2009-03-06 15:37:02.484000
>>> today.strftime('%j')
'065'

Bearbeiten

Wie in den Kommentaren erwähnt, müssen Sie, wenn Sie Vergleiche oder Berechnungen mit dieser Nummer durchführen möchten, diese konvertieren, int()da sie strftime()eine Zeichenfolge zurückgibt. In diesem Fall ist es besser, die Antwort von DzinX zu verwenden .

Paolo Bergantino
quelle
1
-1: icky. Besser ist der Algorithmus "Heute minus 1. Januar". Viel sauberer und völlig offensichtlich, ohne ein paar Kleinigkeiten über strftimes '% j' nachzuschlagen.
S.Lott
12
Ernsthaft? Wie ist dieser eklige und subtrahierende 1. Januar nicht? strftime gibt es aus einem Grund. Ich stimme einfach nicht zu. Dies ist meiner Meinung nach viel sauberer.
Paolo Bergantino
1
Die Verwendung von strftime ist indirekt, da eine Zeichenfolge aus einer Zahl erzeugt wird: dem Mitglied timetuple.tm_yday. Lesen Sie die Quelle. Die erzeugte Zeichenfolge sollte vor Berechnungen / Vergleichen in eine Zahl konvertiert werden. Warum also die Mühe machen?
Zot
2
Wenn man den Tag des Jahres in einer Zeichenfolge benötigt, beispielsweise zur Verwendung in einem Dateinamen, ist strftime eine viel sauberere Lösung.
Kapitän_M
13

Die Antwort von DZinX ist eine großartige Antwort auf die Frage. Ich habe diese Frage gefunden, als ich nach der Umkehrfunktion gesucht habe. Ich fand das 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

Ich bin mir der Etikette hier nicht sicher, aber ich dachte, ein Zeiger auf die Umkehrfunktion könnte für andere wie mich nützlich sein.

Dave X.
quelle
6

Ich möchte die Leistung verschiedener Ansätze unter Python 3.4, Linux x64 vorstellen. Auszug aus dem Zeilenprofiler:

      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 es also

yday = (period_end - date(period_end.year, 1, 1)).days
Omikron
quelle
1
Wie haben Sie die Leistung berechnet? Ich habe versucht, time.time zu verwenden, und das sind meine Ergebnisse: def f (): (today - datetime.datetime (today.year, 1, 1)). Days + 1 start = time.time (); f (); print ('Lapsed {}'. Format (time.time () - start)); Lapsed 5.221366882324219e-05 def f (): int (today.strftime ('% j')); start = time.time (); f (); print ('Lapsed {}'. Format (time.time () - start)); Lapsed 7.462501525878906e-05
ssoto
5

Subtrahieren Sie einfach den 1. Januar vom Datum:

import datetime
today = datetime.datetime.now()
day_of_year = (today - datetime.datetime(today.year, 1, 1)).days + 1
fällinde
quelle
1
Nichts gegen Paolo, aber datetime.timedelta wird in Tagen angegeben (sowie natürlich in Sekunden und Mikrosekunden), daher ist es eine natürliche Wahl - sicherlich direkter als die Formatierung von Zeichenfolgen
am
1
d.toordinal () - Datum (d.Jahr, 1, 1) .toordinal () + 1 ist laut Dokumentation Standard. Dies entspricht der akzeptierten Antwort, ohne das gesamte Zeittupel zu erzeugen.
Dingle
5

Wenn Sie Grund haben, die Verwendung des datetimeModuls zu vermeiden , funktionieren diese Funktionen.

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
Barry Andersen
quelle
1

Dieser Code verwendet ein Datum als Eingabeargument und gibt den Tag des Jahres zurück.

from datetime import datetime
date = raw_input("Enter date: ")  ## format is 02-02-2016
adate = datetime.datetime.strptime(date,"%d-%m-%Y")
day_of_year = adate.timetuple().tm_yday
day_of_year
Gajanan Kothawade
quelle