Модуль calendar языка Python

В стандартной библиотеки Python есть модуль calendar, который в первую очередь предназначен для вывода календаря на заданный месяц или целый год на экран

В первом случае используется класс TextCalendar, во втором – HTMLCalendar.

Оба они являются подклассами класса Calendar (следовательно наследуют все его атрибуты), который сам по себе не предназначен для вывода данных. Если этого не требуется, а необходимо только получать коллекции дат, дней недели с привязкой к дате или дню месяца и тому подобное, достаточно использовать Calendar. Также сюда относятся случаи, когда данные должны в последующем сохраняться или передаваться в каких-то особых форматах (не текстовом и не HTML).


Дополнительно в самом модуле calendar есть различные функции и константы, с помощью которых можно узнать день недели даты, является ли год високосным, количество високосных лет между датами и другое.

import calendar
 
# Является ли год високосным
print(calendar.isleap(2000))  # True
print(calendar.isleap(2100))  # False
 
# Строка заголовков дней недели
print(calendar.weekheader(2))  # Mo Tu We Th Fr Sa Su
 
# weekday() возвращает индекс дня недели для заданной даты
june3 = calendar.weekday(2023, 6, 3)
wh = calendar.weekheader(9).split()
print(wh[june3])  # Saturday
 
# Дни недели в текущей локали
dn = calendar.day_name
print(list(dn)[5:])  # ['Saturday', 'Sunday']

Функции month, prmonth, calendar, prcal являются вариантами "быстрого доступа" к соответствующим методам класса TextCalendar: formatmonth, prmonth, formatyear, pryear.

При создании календаря первым днем недели по умолчанию является понедельник. Его индексный номер 0. Индексы всех дней можно узнать через соответствующие константы модуля.

>>> import calendar
>>> calendar.MONDAY
0
>>> calendar.THURSDAY
3
>>> calendar.SUNDAY
6

При создании экземпляра календаря, если требуется, чтобы неделя начиналась с отличного от понедельника дня, следует передать индекс другого дня недели (это можно сделать через константу).

from calendar import TextCalendar
 
monday_cal = TextCalendar()
sunday_cal = TextCalendar(6)
 
monday_cal.prmonth(2023, 6)
sunday_cal.prmonth(2023, 6)
 
m_days = monday_cal.monthdatescalendar(2023, 6)
s_days = sunday_cal.monthdatescalendar(2023, 6)
 
print("\nПервый день первой недели месяца:")
 
print(m_days[0][0], "- если с понедельника")
print(s_days[0][0], "- если с воскресенья")
     June 2023
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
     June 2023
Su Mo Tu We Th Fr Sa
             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

Первый день первой недели месяца:
2023-05-29 - если с понедельника
2023-05-28 - если с воскресенья

Поскольку модуль calendar в первую очередь заточен на вывод данных, работу с группами дат (неделя, месяц), то в данные месяца захватываются все дни первой и последней недели, даже если их даты принадлежат другим месяцам.

Методы monthdatescalendar, monthdayscalendar, monthdays2calendar и аналогичные для года возвращают списки дней месяца или года в разных формах представления.

from calendar import Calendar, SUNDAY
 
cal = Calendar()
 
dates = cal.monthdatescalendar(2023, 6)
 
# Список, состоящий из списков по 7 элементов-дней
print(type(dates))  # <class 'list'>
 
# Количество вложенных списков = сколько недель в месяце
print(len(dates))  # 5
 
# Длина вложенного списка = количество дней в неделе
print(len(dates[0]))  # 7
 
# Тип данных элемента вложенного списка
print(type(dates[0][0]))  # <class 'datetime.date'>
 
# Даты воскресений месяца
for week in dates:
    print(week[SUNDAY], end=', ')  
# 2023-06-04, 2023-06-11, 2023-06-18, 2023-06-25, 2023-07-02,

В отличие от monthdatescalendar элементами вложенных списков, возвращаемых monthdayscalendar и monthdays2calendar, являются целые числа и кортежи соответственно. В первом случае числа обозначают даты месяца. Во втором случае первый элемент кортежа – это дата, второй элемент – индекс дня недели. Если день недели приходится на дату другого месяца, то вместо даты записывается 0.

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

from calendar import Calendar
 
cal = Calendar()
 
year = cal.yeardayscalendar(2023)
 
# Элементами года являются списки-кварталы
print(len(year))  # 4
 
# В первом квартале 3 месяца
print(len(year[0]))  # 3
 
# Кол-во недель в третьем месяце второго квартала
print(len(year[1][2]))  # 5
 
# Даты последней недели июня
print(year[1][2][4])  # [26, 27, 28, 29, 30, 0, 0]
 
# Год, состоящий из списков полугодий, а не кварталов
year = cal.yeardayscalendar(2023, 6)
print(len(year))  # 2

Другими вариациями являются методы с приставкой "iter" (для года таких нет). Они возвращают объекты-итераторы, данные из которых извлекаются последовательно и безвозвратно:

from calendar import Calendar, WEDNESDAY
 
cal = Calendar()
 
dates = cal.itermonthdates(2023, 6)
print(dates)
print(type(dates))
 
for i in dates:
    if i.weekday() == WEDNESDAY:
        print(i)
 
# в dates больше ничего нет
print(next(iter(dates)))
<generator object Calendar.itermonthdates at 0x7f1b14742570>
<class 'generator'>
2023-05-31
2023-06-07
2023-06-14
2023-06-21
2023-06-28
Traceback (most recent call last):
  File "7_iter.py", line 14, in <module>
    print(next(iter(dates)))
StopIteration

В классе HTMLCalendar есть методы, которые возвращают строку с тегами HTML: formatmonth, formatyear.

Данные в таком виде вставляются в исходный код веб-страниц.

Метод formatyearpage класса HTMLCalendar возвращает тип bytes, а не str, и формирует страницу полностью (с начальными и конечными тегами, не относящимися непосредственно к календарю).

Для стилизации календаря класс HTMLCalendar включает поля, значения которых можно заменять на свои путем создания дочернего класса.


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




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