Методы isocalendar и fromisocalendar класса date модуля datetime языка Python

Сразу отметим, что методы isocalendar и fromisocalendar есть не только у date, но и класса datetime. Разница лишь в том, что при получении экземпляра datetime к дате добавляются характеристики времени (со значениями 0), при применении метода isocalendar время игнорируется.

Существует особая разновидность календаря, которую часто используют в деловой среде, – так называемый ISO календарь, он же ISO год, или ISO week date (недельные даты), ISO week-numbering year (понедельно пронумерованный год). Данная вариация календаря является частью стандарта ISO 8601, к которому также относится обычное представление дат.

ISO год состоит из целого количества недель, причем первая неделя всегда начинается с понедельника, а последняя неделя года всегда заканчивается воскресеньем. Это значит, что в большинстве случаев такой год не совпадает с календарным. Кроме того, количество недель в разные года отличается: их может быть 52 или 53.


Даты в формате ISO календаря обозначаются не так, как мы привыкли. Здесь нет месяцев, нет дней месяца. Вместо этого есть номер недели и номер дня недели. Нумерация в обоих случаях начинается с единицы, а не нуля. Например, 2023-W02-1 – это первый день второй недели 2023-го года. И это не 8-е января. Зато это точно понедельник.

С помощью метода fromisocalendar мы можем получить привычную нам дату из недельной даты.

from datetime import date
 
d = date.fromisocalendar(2023, week=2, day=1)
 
print(d)  # 2023-01-09

К какому году относится пограничная неделя, включающая даты старого и нового года, зависит от следующего правила.

Если 1-е января приходится на понедельник, вторник, среду и четверг, то эта неделя считается первой неделей нового года. Она может включать даты старого года.

Если 1-е января приходится на пятницу, субботу, воскресенье, то эта неделя является последней неделей прошлого года. Новый год начнется с более поздней даты.

from datetime import date
import calendar
 
d = date.fromisocalendar(2026, 1, 1)
print(d, "- первый день 2026 года (понедельник)")
 
calendar.prmonth(2026, 1)
 
print()
 
d = date.fromisocalendar(2027, 1, 1)
print(d, "- первый день 2027 года (понедельник)")
 
calendar.prmonth(2027, 1)
2025-12-29 - первый день 2026 года (понедельник)
    January 2026
Mo Tu We Th Fr Sa Su
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

2027-01-04 - первый день 2027 года (понедельник)
    January 2027
Mo Tu We Th Fr Sa Su
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Метод isocalendar выполняет обратное действие: конвертирует обычную дату в формат недельного календаря. В отличие от fromisocalendar, который является методом класса, isocalendar применяется к экземпляру.

from datetime import date
 
d = input("Введите дату в формате ISO: ")
d = date.fromisoformat(d)
 
dw = d.isocalendar()
print("Неделя:", dw.week)
print("День недели:", dw.weekday)
 
print(type(dw))
Введите дату в формате ISO: 2023-07-14
Неделя: 28
День недели: 5
<class 'datetime.IsoCalendarDate'>

Метод isocalendar возвращает экземпляр IsoCalendarDate, данные из которого извлекаются с помощью атрибутов year, week, weekday. Непосредственно создавать объекты от этого класса нельзя.

Для того, чтобы узнать номер последней недели года, то есть сколько недель включает год, можно вызвать isocalendar на 28 декабря. Это та дата, которая всегда принадлежит текущему году и всегда находится в пределах последней его недели.

from datetime import date
 
for i in range(2020, 2030):
    weeks = date(i, 12, 28).isocalendar().week
    print(f'{i}: {weeks}', end=' ')
    if weeks == 53:
        print("- big year!")
    else:
        print()
2020: 53 - big year!
2021: 52 
2022: 52 
2023: 52 
2024: 52 
2025: 52 
2026: 53 - big year!
2027: 52 
2028: 52 
2029: 52

Поскольку ISO год всегда содержит целое число недель, чтобы узнать количество дней в году, надо количество недель умножить на 7. Таким образом, в 52-недельном годе содержится 264 дня, в 53-недельном на семь дней больше, то есть 371.


Даты и время в Python. Курс




Все разделы сайта