Uzyskaj datę z numeru tygodnia

88

Proszę, co jest nie tak z moim kodem:

import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d, "%Y-W%W")
print(r)

Wyświetl „2013-01-01 00:00:00”, dzięki.

Ali powiedział OMAR
źródło

Odpowiedzi:

175

Numer tygodnia nie wystarczy, aby wygenerować datę; potrzebujesz również dnia tygodnia. Dodaj domyślne:

import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d + '-1', "%Y-W%W-%w")
print(r)

-1I -%wwzorzec mówi parser odebrać w poniedziałek w tym tygodniu. To daje:

2013-07-01 00:00:00

%Wużywa poniedziałku jako pierwszego dnia tygodnia. Chociaż możesz wybrać własny dzień tygodnia, możesz uzyskać nieoczekiwane rezultaty, jeśli odejdziesz od tego.

Zobacz sekcję strftime()i strptime()zachowanie w dokumentacji, przypis 4:

W połączeniu z tą strptime()metodą %Ui %Wsą używane tylko w obliczeniach, gdy określony jest dzień tygodnia i rok.

Uwaga, jeśli Twój numer tygodnia jest datą tygodnia ISO , będziesz chciał użyć %G-W%V-%uzamiast tego! Te dyrektywy wymagają języka Python 3.6 lub nowszego.

Martijn Pieters
źródło
Żałuję, że nie mogę dać ci więcej niż 1 głos ... Machałem głową, żeby dowiedzieć się, dlaczego to nie działa.
Islam Q.
2
Nie działa. datetime.datetime.strptime ("2018-W0-0", "% YW% W-% w") == datetime.datetime.strptime ("2018-W1-0", "% YW% W-% w") -> „2018-01-07 00:00:00”. Pierwszy i drugi tydzień 2018 roku mają tę samą datę rozpoczęcia.
ozw1z5
2
@ ozw1z5rd: to dlatego, że w 2018 roku nie ma tygodnia 0. Tydzień 0 to częściowy tydzień poprzedzający pierwszy poniedziałek roku; w 2018 roku w pierwszy poniedziałek przypada 1 stycznia. Innymi słowy, problemem jest tutaj ciąg wejściowy , a nie technika, a Python ma poprawione błędy, aby zamiast tego interpretować W0 jako W1.
Martijn Pieters
@ ozw1z5rd: Jeśli jest to problem z Twoją aplikacją, musisz uwzględnić takie lata; if d.endswith('-W0') and r.day == 7: raise ValueError('Invalid date string, No week 0 in {}'.format(r.year))
Martijn Pieters
1
@darda: Python 3.6 obsługuje już definicje tygodni ISO 8601, użyj %G(rok przez większą część tygodnia) iw %Vtakim przypadku.
Martijn Pieters
27

Aby uzupełnić pozostałe odpowiedzi - jeśli korzystasz z numerów tygodni ISO , ten ciąg jest odpowiedni (aby uzyskać poniedziałek z danego numeru tygodnia ISO):

import datetime
d = '2013-W26'
r = datetime.datetime.strptime(d + '-1', '%G-W%V-%u')
print(r)

%G, %V, %uSą odpowiednikami ISO o %Y, %W, %w, więc wyjść:

2013-06-24 00:00:00

Dostępne w Pythonie 3.6+; z dokumentów .

Luka Kikelj
źródło
14

W Pythonie 3.8 jest przydatne datetime.date.fromisocalendar:

>>> from datetime import date
>>> date.fromisocalendar(2020, 1, 1)  # (year, week, day of week)
datetime.date(2019, 12, 30, 0, 0)

W starszych wersjach Pythona (3.7-) obliczenia mogą wykorzystywać informacje z datetime.date.isocalendardo określenia tygodni tygodnia zgodnych z ISO8601:

from datetime import date, timedelta

def monday_of_calenderweek(year, week):
    first = date(year, 1, 1)
    base = 1 if first.isocalendar()[1] == 1 else 8
    return first + timedelta(days=base - first.isocalendar()[2] + 7 * (week - 1))

Oba działa również z datetime.datetime.

Jens W. Klein
źródło
6
import datetime
res = datetime.datetime.strptime("2018 W30 w1", "%Y %W w%w")
print res

Dodanie 1 jako dnia tygodnia da dokładny początek bieżącego tygodnia. Dodanie timedelta (dni = 6) da ci koniec tygodnia.

datetime.datetime(2018, 7, 23)
Senthilkumar C.
źródło
@Senthikumar C, które powinno być jak poniżejres = datetime.datetime.strptime("2018 W30 w1", "%Y W%W w%w")
MD Alauddin Al-Amin
1

Jeśli masz roczny numer tygodnia, po prostu dodaj liczbę tygodni do pierwszego dnia roku.

>>> import datetime
>>> from dateutil.relativedelta import relativedelta

>>> week = 40
>>> year = 2019
>>> date = datetime.date(year,1,1)+relativedelta(weeks=+week)
>>> date
datetime.date(2019, 10, 8)
dimosbele
źródło
0

Oto przydatna funkcja obejmująca problem z tygodniem zerowym.

Ron
źródło