Как в Python получить дату на основе года, номера недели и дня недели?

Учитывая значение даты и число, я хочу увидеть, как это число сравнивается с числом эквивалентного дня в предыдущие годы.

Под «эквивалентным днем» я подразумеваю один и тот же номер недели и тот же день недели, а НЕ одну и ту же дату в календаре.

Например, начиная с такой даты, как 25 мая 1975 года:

>>> holyGrail = datetime.datetime(1975,5,25)

это седьмой день 21-й недели:

>>> holyGrail.isocalendar()
(1975, 21, 7)
>>>

Я хочу вытащить даты 7-го дня 21-й недели 1974, 1973 и т. Д.

По сути, я хочу сделать что-то вроде этого:

>>> yearBack = datetime.datetime().isocalendar(1974,21,7)

и пусть он вернет мне дату, соответствующую этой неделе и буднему дню, в данном случае это будет 26 мая 1974 года, а не 25-е:

>>> yearBack = datetime.datetime(1974,5,26)
>>> yearBack.isocalendar()
(1974, 21, 7)
>>>

Я вижу из https://stackoverflow.com/a/28069361/5324657, что существует (недокументированный?) Формат% V на strftime(), возвращая номер недели ISO-8601, который работает нормально в strftime и кажется мне тем, что мне нужно, однако, когда я пытаюсь использовать тот же формат% V в strptime(), я получаю сообщение об ошибке

ValueError: 'V' is a bad directive in format '%Y-%V-%w'

Как я могу легко / надежно найти эквивалентные даты Год / Неделя / День недели, возвращаясь во времени?

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


person Jeremy Jones    schedule 05.12.2016    source источник
comment
Дубликат stackoverflow.com/a/7687085/5324657, но этот удобный модуль isoweek не встроен. Есть ли встроенный способ сделать это?   -  person Jeremy Jones    schedule 05.12.2016
comment
Этот повторяющийся вопрос также дает единственные встроенные способы сделать это; если ваше определение недели не соответствует Python (и вы не можете использовать Python 3.6, совместимый с ISO strptime), тогда нет, нет (умеренно чистого) встроенного способа. Желание быть встроенным еще не значит.   -  person ShadowRanger    schedule 05.12.2016


Ответы (1)


Я думаю, это должно сработать:

def getDate(d, y):
    s = datetime.date(y, 1, 1)
    while s.isocalendar()[2] != 4:
        s += datetime.timedelta(days=1)
    s += datetime.timedelta(weeks=d.isocalendar()[1]-1,
                            days=d.isocalendar()[2]-s.isocalendar()[2])
    if d.isocalendar()[-2:] == s.isocalendar()[-2:]:
         return s
    raise ValueError("{} has no equivalent in {}".format(d, y))

В григорианском календаре в некоторых годах 52 недели, а в некоторых - 53, поэтому не всегда есть эквивалентная дата. В этих случаях он вызовет ValueError.

>>>print(getDate(datetime.date(1975, 5, 25), 1974))
1974-05-26

>>>print(getDate(datetime.date(1975, 5, 25), 1973))
1973-05-27

>>>print(getDate(datetime.date(1975, 5, 25), 1972))
1972-05-28

>>>print(getDate(datetime.date(1904, 1, 03), 1978))
ValueError: 1904-01-03 has no equivalent in 1978
person Kevin Schellenberg    schedule 05.12.2016
comment
Этот tm_yday действительно полезен, но я эквивалентен дню недели: я начинаю с «Воскресенье 21 недели в 1975 году», поэтому мне нужна дата «Воскресенье 21 недели» для 1974 (26 мая) и 1973 (27 мая). ) и 1972 г. (28 мая) и т. д. - person Jeremy Jones; 05.12.2016
comment
В ПОРЯДКЕ. Я скорректировал свой ответ. - person Kevin Schellenberg; 05.12.2016