Получить дату по номеру недели

88

Пожалуйста, что не так с моим кодом:

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

Отображение «2013-01-01 00:00:00», спасибо.

Али САИД ОМАР
источник

Ответы:

175

Для создания даты недостаточно номера недели; вам также нужен день недели. Добавьте значение по умолчанию:

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

-1И -%wшаблон говорит анализатор , чтобы выбрать понедельник в этой неделе. Это выводит:

2013-07-01 00:00:00

%Wиспользует понедельник как первый день недели. Хотя вы можете выбрать свой собственный день недели, вы можете получить неожиданные результаты, если отклонитесь от него.

См. Раздел strftime()и strptime()поведение в документации, сноска 4:

При использовании с strptime()методом %Uи %Wиспользуются в расчетах только в том случае, если указаны день недели и год.

Обратите внимание: если номер вашей недели соответствует дате недели в формате ISO , вы захотите использовать ее %G-W%V-%uвместо этого! Для этих директив требуется Python 3.6 или новее.

Мартейн Питерс
источник
Хотел бы я дать вам больше одного голоса ... Я тряс головой, пытаясь понять, почему это не работает.
Ислам К.
2
Не работает. datetime.datetime.strptime ("2018-W0-0", "% YW% W-% w") == datetime.datetime.strptime ("2018-W1-0", "% YW% W-% w") -> «2018-01-07 00:00:00». Первая и вторая неделя 2018 года имеют одинаковую дату начала.
ozw1z5rd 09
2
@ ozw1z5rd: это потому, что в 2018 году нет недели 0. Неделя 0 - это неполная неделя перед первым понедельником года; в 2018 году первый понедельник - 1 января. Другими словами, проблема здесь в вашей строке ввода , а не в технике, и Python исправил ошибки, чтобы интерпретировать W0 как W1.
Мартейн Питерс
@ ozw1z5rd: Если это проблема для вашего приложения, вам нужно будет указать такие годы в особом случае; if d.endswith('-W0') and r.day == 7: raise ValueError('Invalid date string, No week 0 in {}'.format(r.year))
Мартейн Питерс
1
@darda: Python 3.6 уже поддерживает определения недель ISO 8601, использование %G(год для большей части недели) и %Vв этом случае.
Мартейн Питерс
27

Чтобы завершить другие ответы - если вы используете номера недель ISO , эта строка подходит (чтобы получить понедельник данного номера недели ISO):

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

%G, %V, %uЯвляются ISO эквиваленты %Y, %W, %w, так что выходы:

2013-06-24 00:00:00

Доступен в Python 3.6+; из документов .

Лука Кикель
источник
14

В Python 3.8 есть удобные datetime.date.fromisocalendar:

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

В более старых версиях Python (3.7-) при вычислении можно использовать информацию из, datetime.date.isocalendarчтобы определить неделю, соответствующую 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))

Оба работают также с datetime.datetime.

Йенс В. Кляйн
источник
6
import datetime
res = datetime.datetime.strptime("2018 W30 w1", "%Y %W w%w")
print res

Добавление 1 в качестве дня недели даст точное начало текущей недели. Добавление timedelta (дней = 6) даст вам конец недели.

datetime.datetime(2018, 7, 23)
Сентилкумар С
источник
@Senthikumar C, который должен быть таким, как показано нижеres = datetime.datetime.strptime("2018 W30 w1", "%Y W%W w%w")
доктор медицины Алауддин Аль-Амин,
1

Если у вас есть годовой номер недели, просто добавьте количество недель к первому дню года.

>>> 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)
димосбеле
источник