Was ist der beste Weg, um die Umkehrung von datetime.isocalendar () zu finden?

StackOverflow https://stackoverflow.com/questions/304256

  •  08-07-2019
  •  | 
  •  

Frage

Der Python datetime.isocalendar() Methode gibt ein Tupel (ISO_year, ISO_week_number, ISO_weekday) für das gegebene datetime Objekt. Gibt es eine entsprechende inverse Funktion? Wenn nicht, gibt es eine einfache Möglichkeit, ein Datum im Jahr, Woche und Tag der Woche gegeben zu berechnen?

War es hilfreich?

Lösung

Vor kurzem hatte ich dieses Problem selbst zu lösen, und kam mit dieser Lösung:

import datetime

def iso_year_start(iso_year):
    "The gregorian calendar date of the first day of the given ISO year"
    fourth_jan = datetime.date(iso_year, 1, 4)
    delta = datetime.timedelta(fourth_jan.isoweekday()-1)
    return fourth_jan - delta 

def iso_to_gregorian(iso_year, iso_week, iso_day):
    "Gregorian calendar date for the given ISO year, week and day"
    year_start = iso_year_start(iso_year)
    return year_start + datetime.timedelta(days=iso_day-1, weeks=iso_week-1)

Ein paar Testfälle:

>>> iso = datetime.date(2005, 1, 1).isocalendar()
>>> iso
(2004, 53, 6)
>>> iso_to_gregorian(*iso)
datetime.date(2005, 1, 1)

>>> iso = datetime.date(2010, 1, 4).isocalendar()    
>>> iso
(2010, 1, 1)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 4)

>>> iso = datetime.date(2010, 1, 3).isocalendar()
>>> iso
(2009, 53, 7)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 3)

Andere Tipps

import datetime

def iso_to_gregorian(iso_year, iso_week, iso_day):
    "Gregorian calendar date for the given ISO year, week and day"
    fourth_jan = datetime.date(iso_year, 1, 4)
    _, fourth_jan_week, fourth_jan_day = fourth_jan.isocalendar()
    return fourth_jan + datetime.timedelta(days=iso_day-fourth_jan_day, weeks=iso_week-fourth_jan_week)

Dies wurde von @ BenJames der sehr guten Antwort angepasst. Sie müssen nicht den ersten Tag des Jahres kennen. Sie haben nur ein Beispiel für einen Zeitpunkt zu wissen, was sicherlich in dem gleichen ISO Jahr, und die ISO Kalenderwoche und Tag von diesem Datum.

Der 4. Januar ist nur ein Beispiel, weil, wie Ben wies darauf hin, immer der 4. Januar auf das gleiche ISO Jahr und Gregorianische Jahr gehört, und ist der erste Tag des Jahres zu tun.

Seit Wochen alle gleich lang sind, können Sie einfach abziehen die Tage und Wochen zwischen dem ISO von Datum, das Sie möchten, und die ISO nach dem Datum, das Sie in beiden Formen kennen, und fügen Sie auf diese Anzahl von Tagen und Wochen . (Es spielt keine Rolle, ob diese Zahlen positiv oder negativ sind, so könnte man eine andere ‚festen Tag‘ wie 28. Dezember wählen.)

Bearbeiten

ich korrigiert, weil, wie @JoSo helfend gerichtet war, der erste Tag des Gregorianischen Jahres, die das ISO-Jahr gehört auch 4. Januar ist nicht 5. Januar. Wie die Erklärung sagt, spielt es keine Rolle, welches Datum als Bezugspunkt gewählt wird, aber der 4. Januar der Wahl macht diese Wahl weniger ‚Magie‘.

Wie von Python 3.6, können Sie die neuen %G, %u und %V Richtlinien verwenden. Siehe Ausgabe 12006 und die aktualisierte Dokumentation :

  

%G
  ISO 8601 Jahr mit Jahrhundert repräsentiert das Jahr, das den größten Teil der ISO Woche enthält (%V).

     

%u
  ISO 8601 Wochentag als Dezimalzahl, wobei 1 am Montag.

     

%V
  ISO 8601 Woche als Dezimalzahl mit Montag als erster Tag der Woche. Woche 01 ist die Woche enthält 4. Januar.

Bei einer Zeichenkette mit Jahr, Wochennummer und Wochentag Nummer, ist es einfach, die heraus zu einem Datum zu analysieren mit:

from datetime import datetime

datetime.strptime('2002 01 1', '%G %V %u').date()

oder als Funktion mit ganzzahligen Eingänge:

from datetime import datetime

def date_from_isoweek(iso_year, iso_weeknumber, iso_weekday):
    return datetime.strptime(
        '{:04d} {:02d} {:d}'.format(iso_year, iso_weeknumber, iso_weekday),
        '%G %V %u').date()

Ab Python 3.6, datetime.strptime() werden die %G, %V und %u Richtlinien unterstützen, so können Sie einfach tun datetime.strptime('2015 1 2', '%G %V %u').date(). Siehe: https://hg.python.org/cpython/rev/acdebfbfbdcf

Für die nächsten Leute hier kommen, eine kürzere, Single-def Version von Bens gute Lösung:

def iso_to_gregorian(iso_year, iso_week, iso_day):
    jan4 = datetime.date(iso_year, 1, 4)
    start = jan4 - datetime.timedelta(days=jan4.isoweekday()-1)
    return start + datetime.timedelta(weeks=iso_week-1, days=iso_day-1)

Beachten Sie, dass% W ist die Woche # (0-53), die nicht das gleiche wie die ISO-Woche ist (1-53). Es wird Rand Fälle, in denen% W wird nicht funktionieren.

kam ich mit einer Lösung auf, ähnlich dem von Ben James geschrieben, aber eine einzige Funktion:

import datetime
def getDateFromWeek(year,week,day):
    """Method to retrieve the date from the specified week, year and weekday"""

    year_start = datetime.date(year,1,1)
    ys_weekday =  year_start.weekday()
    delta = (week*7)+(day-ys_weekday)
    if ys_weekday<4:
        delta -= 7

    return  year_start  + datetime.timedelta(days=delta)

Getestet habe ich es aus mit Randwerte wie die letzte Woche des Jahres 2020 und der ersten Woche von 2021, und es funktionierte ziemlich gut aus.

EDIT: ignorieren diese, die Grenzfälle sind ein Schmerz. Gehen Sie mit Ben-Lösung.

Ok, bei näherem Hinsehen bemerkte ich, dass strptime %W und %w Parameter hat, so dass die folgenden Werke:

def fromisocalendar(y,w,d):
   return datetime.strptime( "%04dW%02d-%d"%(y,w-1,d), "%YW%W-%w")

Ein paar gotchas: Die ISO-Wochennummer beginnt bei 1, während %W bei 0 beginnt. Der ISO-Woche Tag beginnt um 1 (Montag), die die gleiche wie %w ist, so Sonntag würde wahrscheinlich 0 werden muß, nicht 7 ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top