Как написать календарь на python

Одна из первых программ, которую можно попробовать написать на Python — это календарь. Она не сложная, но при всем при этом, с её помощью можно потренировать навыки работы со стандартными библиотеками Tkinter и calendar.

Описание программы

Календарь написан на Python 3 с помощью графической библиотеки Tkinter. Для определения текущего дня недели и количества дней в месяце использовалась стандартная библиотека calendar. Будем отображать календарь на текущий месяц в виде таблицы. Текущую дату выделим зелёным цветом. Также добавим кнопки для перелистывания месяцев.

Подключение библиотек и объявление переменных

Подключаем стандартные библиотеки Tkinter, datetime и calendar с помощью import. Инициализируем класс root, с помощью которого будет отрисовываться графический интерфейс. Задаем заголовок окна «Calendar». Объявляем пустой список days. В дальнейшем в нем будут храниться поля таблицы. Каждое такое поле соответствует определенному дню.

В переменную now будем хранить текущую дату. В переменных year и month будут храниться год и месяц, календарь которых в данный момент отображается.

from tkinter import *
import calendar
import datetime
root = Tk()
root.title('Calendar')
days = []
now = datetime.datetime.now()
year = now.year
month = now.month

Меняем текущий месяц

Функции prew и next будут вызываться при нажатии на одну из клавиш смены месяца. Если текущее значение месяца «январь» и пользователь нажмет на кнопку перехода на предыдущий месяц, то тогда уменьшится год и месяц поменяет значение на «декабрь».

Обратите внимание на то, что переменные month и year глобальные. Поэтому перед изменением их значения в функции необходимо использовать ключевое слово global.

Функция fill перерисовывает календарь.

def prew():
    global month, year
    month -= 1
    if month == 0:
        month = 12
        year -= 1
    fill()

def next():
    global month, year
    month += 1
    if month == 13:
        month = 1
        year += 1
    fill()

Перерисовка календаря

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

Вначале выводим наименование месяца и год. Вычисляем количество дней в предыдущем месяце и записываем в переменную prew_month_days. В переменноу week_day запишем номер дня недели первого числа месяца (от 0 – если первое число выпадет на понедельник, до 6 — на воскресенье).

После этого в трех циклах выводим числа и их корректируем их цвета:

  1. В первом цикле заполняем номера дней выбранного месяца. Отображать будем их черным цветом. Если это текущий день, то его фон делаем зелёным.
  2. Во втором цикле заполняем числа предыдущего месяца. Они отображаться будут серым цветом.
  3. В третьем цикле добавляем числа следующего месяца. Их также выводим серым цветом.
def fill():
    info_label['text'] = calendar.month_name[month] + ', ' + str(year)
    month_days = calendar.monthrange(year, month)[1]
    if month == 1:
        prew_month_days = calendar.monthrange(year-1, 12)[1]
    else:
        prew_month_days = calendar.monthrange(year, month - 1)[1]
    week_day = calendar.monthrange(year, month)[0]
    for n in range(month_days):
        days[n + week_day]['text'] = n+1
        days[n + week_day]['fg'] = 'black'
        if year == now.year and month == now.month and n == now.day:
            days[n + week_day]['background'] = 'green'
        else:
            days[n + week_day]['background'] = 'lightgray'
    for n in range(week_day):
        days[week_day - n - 1]['text'] = prew_month_days - n
        days[week_day - n - 1]['fg'] = 'gray'
        days[week_day - n - 1]['background'] = '#f3f3f3'
    for n in range(6*7 - month_days - week_day):
        days[week_day + month_days + n]['text'] = n+1
        days[week_day + month_days + n]['fg'] = 'gray'
        days[week_day + month_days + n]['background'] = '#f3f3f3'

Отображение элементов

Для отображения календаря в Python 3 мы используем библиотеку Tkinter. Воспользуемся её упаковщиком grid. Он представит все создаваемые нами элементы в виде таблицы.

В первой строке в крайней левой и крайней правой ячейках (с номерами столбцов 0 и 6) отобразим кнопки смены месяцев. По центру выведем текстовое поле, в котором будет отображаться текущий год и месяц. Это поле будет занимать 5 ячеек таблицы, поэтому выставим параметр columnspan в 5.

prew_button = Button(root, text='<', command=prew)
prew_button.grid(row=0, column=0, sticky='nsew')
next_button = Button(root, text='>', command=next)
next_button.grid(row=0, column=6, sticky='nsew')
info_label = Label(root, text='0', width=1, height=1, 
            font=('Verdana', 16, 'bold'), fg='blue')
info_label.grid(row=0, column=1, columnspan=5, sticky='nsew')

Во второй строке выведем сокращенные названия месяцев.

Дальше отображаем 6 строк по 7 столбцов, которые будем заполнять числами, обозначающими номера дней.

В завершении используем функцию fill, которая заполнит наш календарь начальными данными – календарем текущего месяца. После этого запустим цикл обработки событий mainloop.

for n in range(7):
    lbl = Label(root, text=calendar.day_abbr[n], width=1, height=1, 
                font=('Verdana', 10, 'normal'), fg='darkblue')
    lbl.grid(row=1, column=n, sticky='nsew')
for row in range(6):
    for col in range(7):
        lbl = Label(root, text='0', width=4, height=2, 
                    font=('Verdana', 16, 'bold'))
        lbl.grid(row=row+2, column=col, sticky='nsew')
        days.append(lbl)
fill()
root.mainloop()

Пример программы на Python 3 для вывода календаря с помощью библиотеки Tkinter достаточно прост. Он поможет программистам в изучении языка. Здесь у нас представлены различные условные операторы и циклы, работа с глобальными переменными в функциях. Самое сложное в этом примере – это отображение графических элементов.

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

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

calendar.Calendar(firstweekday=0) — класс календаря. firstweekday — первый день недели (0 — понедельник, 6 — воскресенье).

Методы:

iterweekdays() — итератор дней недели, начиная с firstweekday.

itermonthdates(year, month) — итератор для месяца month года year. Возвращает все дни этого месяца (как объекты datetime.date), а также дни до и после этого месяца до полной недели.

itermonthdays2(year, month) — как itermonthdates, только дни возвращаются не как datetime.date объекты, а кортежи (номер дня, номер дня недели).

itermonthdays(year, month) — как itermonthdates, только дни возвращаются не как datetime.date объекты, а номера дней.

monthdatescalendar(year, month) — список недель в месяце. Неделя — список из 7 объектов datetime.date.

monthdays2calendar(year, month) — как monthdatescalendar, но объекты — кортежи (номер дня, номер дня недели).

monthdayscalendar(year, month) — как monthdatescalendar, но объекты — номера дней.


calendar.TextCalendar(firstweekday=0) — класс для генерации текстового календаря.

Методы:

formatmonth(theyear, themonth, w=0, l=0) — возвращает календарь на месяц в виде строки, с шириной колонки w и высотой l.

prmonth(theyear, themonth, w=0, l=0) — печатает календарь на месяц.

formatyear(theyear, w=2, l=1, c=6, m=3) — возвращает календарь на год; из m колонок, шириной даты w, высотой недели l и количеством пробелов между месяцами c.

pryear(theyear, w=2, l=1, c=6, m=3) — печатает календарь на год.


calendar.HTMLCalendar(firstweekday=0) — класс для генерации HTML календаря.

Методы:

formatmonth(theyear, themonth, withyear=True) — календарь на месяц в виде HTML таблицы. Если withyear True, номер года будет включен в заголовок.

formatyear(theyear, width=3) — календарь на год в виде HTML таблицы. width — количество месяцев в ряду.

formatyearpage(theyear, width=3, css=»calendar.css», encoding=None) — календарь на год в виде полноценной HTML страницы, с подключением файла css (который вы можете создать сами), и в кодировке encoding.


calendar.LocaleTextCalendar(firstweekday=0, locale=None) — позволяет создать текстовый календарь с названиями на родном языке.

calendar.LocaleHTMLCalendar(firstweekday=0, locale=None) — позволяет создать HTML календарь с названиями на родном языке.

Например, вот такой календарик получился у меня:

import calendar
a = calendar.LocaleHTMLCalendar(locale='Russian_Russia')
with open('calendar.html', 'w') as g:
    print(a.formatyear(2014, width=4), file=g)
2014
Январь
Пн Вт Ср Чт Пт Сб Вс
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
Февраль
Пн Вт Ср Чт Пт Сб Вс
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
Март
Пн Вт Ср Чт Пт Сб Вс
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
Апрель
Пн Вт Ср Чт Пт Сб Вс
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
Май
Пн Вт Ср Чт Пт Сб Вс
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
Июнь
Пн Вт Ср Чт Пт Сб Вс
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
Июль
Пн Вт Ср Чт Пт Сб Вс
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
Август
Пн Вт Ср Чт Пт Сб Вс
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
Сентябрь
Пн Вт Ср Чт Пт Сб Вс
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
Октябрь
Пн Вт Ср Чт Пт Сб Вс
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
Ноябрь
Пн Вт Ср Чт Пт Сб Вс
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
Декабрь
Пн Вт Ср Чт Пт Сб Вс
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

Также модуль calendar предоставляет несколько полезных функций:

calendar.setfirstweekday(weekday) — устанавливает первый день недели (0 — понедельник, 6 — воскресенье). Также предоставлены значения calendar.MONDAY, calendar.TUESDAY, calendar.WEDNESDAY, calendar.THURSDAY, calendar.FRIDAY, calendar.SATURDAY и calendar.SUNDAY.

calendar.firstweekday() — возвращает первый день недели.

calendar.isleap(year) — является ли год високосным.

calendar.leapdays(y1, y2) — количество високосных лет в последовательности от y1 до y2.

calendar.weekday(year, month, day) — день недели для этой даты.

calendar.monthrange(year, month) — день недели первого дня месяца и количество дней в этом месяце.

Руководство по Python CALENDAR с примером

От автора: модуль календаря в Python содержит класс календаря, который позволяет выполнять вычисления для различных задач на основе даты, месяца и года. Кроме того, классы Python TextCalendar и HTMLCalendar позволяют редактировать календарь и использовать его в соответствии с вашими потребностями.

Давайте рассмотрим, что мы можем сделать с Python Calendar.

Шаг 1) Запустите код.

Строка кода 1: Мы начинаем с «import calendar», который импортирует все классы этого модуля.

Хотите узнать, что необходимо для создания сайта?

Посмотрите видео и узнайте пошаговый план по созданию сайта с нуля!

Смотреть видео

Строка кода 3: c = calendar.TextCalendar (calendar.SUNDAY) указывает интерпретатору создать текстовый календарь. Начало месяца будет воскресенье. В Python вы можете отформатировать календарь, так как вы можете изменить день, с которого начинать месяц.

Строка кода 4: str = c.formatmonth (2025,1) создает календарь на 2025 год, месяц 1 — январь

Строка кода 5: print str выводит результат.

Давайте изменим значение с воскресенья на четверг и проверим вывод.

Шаг 2) Вы также можете вывести Календарь в формате HTML, эта функция полезна для разработчиков, если они хотят внести какие-либо изменения во внешний вид календаря.

Шаг 3) Перебираем через цикл дни месяца с помощью c.itermonthday(2025,4), мы получим общее количество дней в этом месяце.

Когда вы выполните код, чтобы получить общее количество дней для определенного месяца, скажем, апреля, вы получите 30 дней, но вы также увидите несколько нулей вместе с этими днями в начале, а иногда и в конце.

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

Эти нули появляются в выводе, потому что в коде вы указали день (четверг), поэтому при вызове функции «c.itermonthdays» она начнет отсчет дней с четверга, и четверг может приходиться не на 1апреля, а на 28 или 29 марта, так что при выполнении кода она начнет отсчет дней с 28 марта. Дни с 28 марта до 1 апреля будут засчитываться как ноль, и в выходных данных вы увидите эти нули, и то же самое применимо к концу месяца.

Таким образом, кроме дат 1-30 все даты из предыдущего, а также последующего месяцев будут отображаться в выходных данных как нули.

Шаг 4) Вы можете получить данные из локальной системы, например, месяцы или дни недели и т. д.

Мы вывели название месяца из локальной системы. Кроме того, вы также можете получить название дня недели, как показано ниже

Хотите узнать, что необходимо для создания сайта?

Посмотрите видео и узнайте пошаговый план по созданию сайта с нуля!

Смотреть видео

Выходные данные будут зависеть от локальной системы. Предположим, что ваша локальная система находится в других странах, она выдаст выходные данные в соответствии с локальными настройками страны. Здесь у нас месяцы, поэтому не будет никакой разницы, но если это будет неделя или день, они, безусловно, будут другими.

Шаг 5) Вы можете получить список для определенного дня недели на целый год. Например, каждый первый понедельник недели. Если вы хотите знать дату первого понедельника для каждого месяца, вы можете использовать этот код.

mycal = calendar.monthcalendar (2025, месяц) создаст календарь на месяц

Устанавливаем переменные week1 и week2 для первой и второй недели календаря

Проверяем, содержит ли неделя 1 понедельник, устанавливаем контрольный день

В противном случае устанавливаем контрольный день как первый понедельник на неделе 2

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

Длина этого объекта Cal будет определенного размера в зависимости от того, сколько недель в этом месяце. В нашем случае это будет один или два, так как первый понедельник недели будет в первую неделю чаще всего, но если нет, то мы рассмотрим вторую неделю. Давайте рассмотрим подробно, почему мы также учитываем вторую неделю.

Здесь мы используем постоянную календаря Monday, объект календаря предоставляет константы, которые представляют Sunday, Monday, Tuesday и так далее. Мы рассмотрели это ранее. Итак, если на первой неделе день, представленный константой Monday, не равен 0, он принадлежит этому месяцу. Если он равен нулю, это будет понедельник, который относится к предыдущему месяцу. Но если первый понедельник не равен 0, это означает, что контрольный день будет в первой неделе. Иначе, если это 0, тогда первый понедельник не в первой неделе месяца, он должен быть во второй.

Контрольный день будет возвращен с тем, какой на какой неделе он будет.

Вот полный код

Пример Python 2

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

32

33

34

import calendar

# Создаем обычный текстовый календарь

c = calendar.TextCalendar(calendar.THURSDAY)

str = c.formatmonth(2025, 1, 0, 0)

print str

# Создаем календарь в формате HTML

hc = calendar.HTMLCalendar(calendar.THURSDAY)

str = hc.formatmonth(2025, 1)

print str

# перебираем через цикл дни месяца

# нули указывают, что дни принадлежат смежному месяцу

for i in c.itermonthdays(2025, 4):

    print i

    # Календарь может выдавать информацию на основе локальных настроек, таких как название дней и месяцев (полных или сокращенных)

    for name in calendar.month_name:

        print name

    for day in calendar.day_name:

        print day

    # вычисляем день на основе правил: Например для каждого второго понедельника каждого месяца

    # Устанавливаем это для каждого месяца, мы можем использовать следующий скрипт

    for month in range(1, 13):

# Он извлекает список недель, который представляет месяц

        mycal = calendar.monthcalendar(2025, month)

# Первый MONDAY должен принадлежать первой или второй неделе

        week1 = mycal[1]

        week2 = mycal[2]

        if week1[calendar.MONDAY] != 0:

            auditday = week1[calendar.MONDAY]

        else:

        # если первый MONDAY не принадлежит первой неделе, он должен быть на второй неделе

        auditday = week2[calendar.MONDAY]

print «%10s %2d» % (calendar.month_name[month], auditday)

Пример Python 3

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

32

33

34

import calendar

# Создаем обычный текстовый календарь

c = calendar.TextCalendar(calendar.THURSDAY)

str = c.formatmonth(2025, 1, 0, 0)

print(str)

# Создаем календарь в формате HTML

hc = calendar.HTMLCalendar(calendar.THURSDAY)

str = hc.formatmonth(2025, 1)

print(str)

# перебираем через цикл дни месяца

# нули указывают, что дни принадлежат смежному месяцу

for i in c.itermonthdays(2025, 4):

    print(i)

    # Календарь может выдавать информацию на основе локальных настроек, таких как название дней и месяцев (полных или сокращенных)

    for name in calendar.month_name:

        print(name)

    for day in calendar.day_name:

        print(day)

    # вычисляем день на основе правил: Например для каждого второго понедельника каждого месяца

    # Устанавливаем это для каждого месяца, мы можем использовать следующий скрипт

    for month in range(1, 13):

# Он извлекает список недель, который представляет месяц

        mycal = calendar.monthcalendar(2025, month)

# Первый MONDAY должен принадлежать первой или второй неделе

        week1 = mycal[1]

        week2 = mycal[2]

        if week1[calendar.MONDAY] != 0:

            auditday = week1[calendar.MONDAY]

        else:

        # если первый MONDAY не принадлежит первой неделе, он должен быть на второй неделе

        auditday = week2[calendar.MONDAY]

print(«%10s %2d» % (calendar.month_name[month], auditday))

Резюме:

В Python вы можете отформатировать календарь так, как хотите, вы можете изменить начальный день месяца

Вывести календарь в формате HTML

Получить данные из локальной системы, например, месяцы или дни недели

Получить список определенного дня недели на целый год

Источник: //www.guru99.com

Редакция: Команда webformyself.

Хотите узнать, что необходимо для создания сайта?

Посмотрите видео и узнайте пошаговый план по созданию сайта с нуля!

Смотреть видео

Хотите узнать, что необходимо для создания сайта?

Посмотрите видео и узнайте пошаговый план по созданию сайта с нуля!

Смотреть

Время на прочтение
6 мин

Количество просмотров 27K

image

Предисловие

В бытность работы аналитиком у меня и моих коллег была практически ежедневная необходимость рассчитывать сроки поставок по доработкам. Задача стояла например такая: рассчитать дату поставки доработки начиная с завтра + 40 рабочих дней. За время работы и руководства отделом аналитики автоматизировать данную функцию руки не дошли, но сейчас решил исправиться, тем более что это замечательный и простой проект, который поможет новичкам ознакомиться с основными конструкциями Python.

Чтобы не откладывать ознакомление с данным модулем просто наберите в командной строке:

pip install prod-cal

Гарантирую что проект будет работать на Python 2.7 и Windows 7, т. к. на этой конфигурации он разрабатывался.

Как собирать пакеты и выкладывать в PyPi я описывать не буду, есть достаточно подробные статьи на эту тему, скажу только что с этой задачей может справиться и новичок, так что если Вы подумывали сделать новый модуль, то не откладывайте это в долгий ящик в этом нет ничего сложного.

Главная цель данной статьи разобрать устройство данного модуля и наметить перспективы для его развития сообществом.

Чтобы не плодить календарей в моём календаре можно использовать все методы стандартного модуля calendar.Calendar.

Состав проекта

После установки проект будет доступен в C:Python27Libsite-packagesprodcal, если вы устанавливали пакет в виртуальное окружение, то ищите его в: <домашний каталог вирт. окружения>Libsite-packagesprodcal

Проект можно вообще не устанавливать а скачать его напрямую с сайта PyPi. После чего распаковать и использовать код непосредственно в своём проекте.

Проект состоит из следующих файлов (все с расширением *.py):

  • config — описывает информацию о поддерживаемых календарях и о календаре выбранном по умолчанию
  • service — файл со вспомогательными функциями, вроде приведения типов и т.п., некоторые функции из этого файла мы разберём ниже
  • holidays — файл содержит реализацию основного и пока единственного класса ProdCal
  • каталог prodcals — содержит наборы календарей и файл prod_dict, который содержит реализацию класса ProdDict (о нём также ниже)

Примеры использования

from procal import ProdCal

my_first_prod_cal = ProdCal()

# Проверяем праздничный день 1 мая
my_first_prod_cal.is_work_day(2016, 5, 1)

# Проверяем рабочий день
my_first_prod_cal.is_work_day(2016, 4, 1)

# Проверяем выходной день
my_first_prod_cal.is_work_day(2016, 4, 2)

# Проверяем перенос празничного дня (рабочий день)
my_first_prod_cal.is_work_day(2016, 2, 20)

# Передаём сразу объект даты
my_first_prod_cal.is_work_day(date(2016, 5, 1)

# Передаём в качестве аргумента строку (today - сегодня)
my_first_prod_cal.is_work_day('today')

# Передаём в качестве аргумента строку (yesterday - вчера)
my_first_prod_cal.is_work_day('yesterday')

# Передаём в качестве аргумента строку (tomorrow - завтра)
my_first_prod_cal.is_work_day('tomorrow')

# Проверяем количество рабочих дней в различных месяцах
my_first_prod_cal.count_work_days([2016, 4, 1], [2016, 4, 30])
my_first_prod_cal.count_work_days([2016, 5, 1], [2016, 5, 31])
my_first_prod_cal.count_work_days([2016, 6, 1], [2016, 6, 30])

# Передаём сразу в формате даты и времени
my_first_prod_cal.count_work_days(date(2016, 4, 1), date(2016, 4, 30))
my_first_prod_cal.count_work_days(date(2016, 5, 1), date(2016, 5, 31))
my_first_prod_cal.count_work_days(date(2016, 6, 1), date(2016, 6, 30))

# Передаём дату начала ввиде текста (today, yesterday, tomorrow)
my_first_prod_cal.count_work_days('today', date(2016, 4, 30))
my_first_prod_cal.count_work_days('yesterday', date(2016, 4, 30))
my_first_prod_cal.count_work_days('tomorrow', date(2016, 4, 30))

# Передаём в качестве конечной даты количество дней от даты начала (включительно)
my_first_prod_cal.count_work_days([2016, 4, 1], 30)
my_first_prod_cal.count_work_days('today', 30)

# Проверяем количество выходных дней в различных месяцах
my_first_prod_cal.count_holidays([2016, 4, 1], [2016, 4, 30])
my_first_prod_cal.count_holidays([2016, 5, 1], [2016, 5, 31])
my_first_prod_cal.count_holidays([2016, 6, 1], [2016, 6, 30])

# Передаём сразу в формате даты и времени
my_first_prod_cal.count_holidays(date(2016, 4, 1), date(2016, 4, 30))
my_first_prod_cal.count_holidays(date(2016, 5, 1), date(2016, 5, 31))
my_first_prod_cal.count_holidays(date(2016, 6, 1), date(2016, 6, 30))

# Передаём дату начала ввиде текста (today, yesterday, tomorrow)
my_first_prod_cal.count_holidays('today', date(2016, 4, 30))
my_first_prod_cal.count_holidays('yesterday', date(2016, 4, 30))
my_first_prod_cal.count_holidays('tomorrow', date(2016, 4, 30))

# Передаём в качестве конечной даты количество дней от даты начала (включительно)
my_first_prod_cal.count_holidays([2016, 4, 1], 30)
my_first_prod_cal.count_holidays('today', 30)

# Рассчитываем конечную дату по рабочим дням
my_first_prod_cal.get_date_by_work_days([2016, 4, 1], 21))
my_first_prod_cal.get_date_by_work_days('today', 21)

Реализация

Структура производственного календаря

Все производственные календари находятся в подкаталоге prodcals в виде отдельных файлов. Формат названия файла соотв. буквенному коду страны по ISO в нижнем регистре. Например, росс. производственный календарь находится в файле ru.py.

Файл содержит два словаря: NON_WORK_DAY_DICT и WORK_DAY_DICT, они имеют одинаковую структуру, первый словарь описывает нерабочие дни (праздничные), а второй описывает переносы рабочих дней на выходные. Словари не содержат указания на «стандартные» нерабочие дни субботу и воскресенье.
Календарь описывают два вложенных словаря: в год вкладываются месяцы, значением месяца является список дней.
Для удобства работы с календарём был сделан отдельный класс ProdDict (унаследован от стандартного словаря) в котором реализован метод is_value, который возвращает True или False в зависимости от наличия в словаре переданного значения. На вход данный класс принимает только даты. Реализация класса ProdDict описана в файле prod_dict (расположен в подкаталоге prodcals).

Реализация класса ProdCal

Данный класс может быть создан и без указания каких-либо аргументов, в этом случае будет использован календарь по умолчанию (российский). Если требуется указать какой календарь использовать, то необходимо передать именованный аргумент locale=<значение>, где значение — это код страны по ISO в любом регистре. Пример для создания производственного календаря Украины:

from prodcal import ProdCal
my_prod_cal = ProdCal(locale='UA')

В настоящий момент поддерживаются календари следующих стран: Беларусь, Грузия, Казахстан, Россия, Украина.

Методы класса ProdCal

is_work_day

Вход: дата, список (с int), кортеж аргументов, строка (поддерживает только: ‘today’, tomorrow’, ‘yesterday’)
Выход: bool

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

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

count_work_days, count_holidays

Вход: дата начала, дата окончания (периода), формат дат описан выше.
Выход: int

Описание: подсчитывает количество рабочих дней в заданном периоде (в случае count_work_days), а в случае count_holidays количество выходных дней.

get_date_by_work_days

Вход: дата начала, int
Выход: date

Описание: вычисляет конечную дату по заданному числу рабочих дней.

Описание сервисных функций

Напомню, что сервисные функции находятся в файле service.py.
Простейшая функция get_date_today преобразует переданное значение в необходимую дату, реализация самая незатейливая (пытливым умам предлагаю переписать под более эффективную конструкцию, например выбор из словаря).

def get_date_today(day):
    today = datetime.today().date()
    if 'today' == day:
        return today
    elif 'yesterday' == day:
        return today - timedelta(days=1)
    elif 'tomorrow' == day:
        return today + timedelta(days=1)
    raise ValueError('Unknown string format', day)

Магия возможности использования дат в различных форматах (если так корректно выражаться) реализована в функции cast.

Реализация функции cast

def cast(start_date, end_date):
    if isinstance(start_date, (tuple, list)) and isinstance(end_date, (tuple, list)):
        start_date, end_date = date(*start_date), date(*end_date)

    if isinstance(start_date, str):
        start_date = get_date_today(start_date)
    elif isinstance(start_date, (tuple, list)):
        start_date = date(*start_date)

    if isinstance(end_date, (tuple, list)):
        end_date = date(*end_date)
    elif isinstance(end_date, int):
        end_date = calc_days_by_int(start_date, end_date)

    if isinstance(start_date, date) and isinstance(end_date, date):
        pass
    else:
        raise ValueError("Unknown format for parse")

Вся идея очень простая, проверяем тип переданных аргументов и приводим всё к дате и возвращаем её. Если не разобрались бросаем исключение.

Ещё интересным местом является функция get_prodcals, которая по переданному значению подгружает из подкаталога prodcals нужный календарь. Возможность этого обеспечивается с помощью функции import_module() из стандартной библиотеки importlib, которая интерпретирует переданную строку как путь к модулю. Например: import_module(‘prodcal.prodcals.ru’) эквивалентно from prodcals import ru. Главный смысл использования этой функции в том, чтобы не указывать явно какие календари загружать, что несколько облегчает дальнейшую поддержку.

Поддержка новых календарей

Поддержка новых календарей обеспечивается с помощью добавления в файл config.py данных о новых календарях, написании тестов и загрузки календаря в подкаталог prodcals. Кроме этого делать больше ничего не нужно.

Планы на развитие

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

Также планируется добавить ряд новых функций, например: расчёт даты и времени по переданным часам, написать тесты совместимости с Python3 и поправить некоторые ошибки.

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

Для всех кто хотел бы поучаствовать в развитии этого и проекта доступен этот репозиторий.

Благодарность

Помимо меня в этом проекте участвует Аркадий Аристов из Челябинска, за что ему большое спасибо!

В Python есть встроенный модуль Calendar, который содержит полезные классы и функции для поддержки различных операций с календарем. По умолчанию модуль «Calendar» следует григорианскому календарю, где понедельник – это первый день (0) недели, а воскресенье –последний день недели (6).

В Python модули datetime и time также предоставляют низкоуровневые функции, связанные с календарем. В дополнение к этим модулям, модуль Calendar предоставляет важные функции, связанные с отображением и управлением календарями.

Для печати календарей и управления ими в модуле Calendar есть 3 важных класса: Calendar, TextCalendar и HTMLCalendar. В этой статье мы увидим, как эти классы могут помочь реализовать множество функций, связанных с календарем.

Функциональные возможности

Чтобы использовать модуль Calendar, нам нужно сначала импортировать модуль, используя:

import calendar

Давайте посмотрим на список полезных функций в этом модуле.

Печать календаря на определенный месяц

Мы можем распечатать календарь на определенный месяц, используя следующую функцию:

calendar.month(yyyy, m, w, l)

Аргументы, передаваемые этой функции, – это год (yyyy), месяц (m), ширина столбца даты (w) и количество строк в неделю (l), соответственно. Например, давайте воспользуемся этой функцией для печати календаря на март 2019 года:

print ("Calendar of March 2019 is:")
print (calendar.month(2019, 3, 2, 1))

Вывод:

Calendar of March 2019 is:
     March 2019
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

Печать календаря на определенный год

Мы можем распечатать календарь на целый год, используя следующую функцию:

calendar.calendar(yyyy, w, l, c, m)

Вышеупомянутая функция возвращает календарь на весь год для года, указанного в качестве аргумента. В эту функцию передаются следующие аргументы: год (yyyy), ширина столбца даты (w), количество строк в неделю (l), количество пробелов между столбцом месяца (c), количество столбцов (m).

Например, чтобы распечатать календарь на 2019 год, используйте:

print(calendar.calendar(2019, 2, 2, 6, 3))

Вывод:

January                   February                   March

Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su

    1  2  3  4  5  6                   1  2  3                   1  2  3

 7  8  9 10 11 12 13       4  5  6  7  8  9 10       4  5  6  7  8  9 10

14 15 16 17 18 19 20      11 12 13 14 15 16 17      11 12 13 14 15 16 17

21 22 23 24 25 26 27      18 19 20 21 22 23 24      18 19 20 21 22 23 24

28 29 30 31               25 26 27 28               25 26 27 28 29 30 31



       April                      May                       June

Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su

 1  2  3  4  5  6  7             1  2  3  4  5                      1  2

 8  9 10 11 12 13 14       6  7  8  9 10 11 12       3  4  5  6  7  8  9

15 16 17 18 19 20 21      13 14 15 16 17 18 19      10 11 12 13 14 15 16

22 23 24 25 26 27 28      20 21 22 23 24 25 26      17 18 19 20 21 22 23

29 30                     27 28 29 30 31            24 25 26 27 28 29 30



        July                     August                  September

Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su

 1  2  3  4  5  6  7                1  2  3  4                         1

 8  9 10 11 12 13 14       5  6  7  8  9 10 11       2  3  4  5  6  7  8

15 16 17 18 19 20 21      12 13 14 15 16 17 18       9 10 11 12 13 14 15

22 23 24 25 26 27 28      19 20 21 22 23 24 25      16 17 18 19 20 21 22

29 30 31                  26 27 28 29 30 31         23 24 25 26 27 28 29

                                                    30



      October                   November                  December

Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su

    1  2  3  4  5  6                   1  2  3                         1

 7  8  9 10 11 12 13       4  5  6  7  8  9 10       2  3  4  5  6  7  8

14 15 16 17 18 19 20      11 12 13 14 15 16 17       9 10 11 12 13 14 15

21 22 23 24 25 26 27      18 19 20 21 22 23 24      16 17 18 19 20 21 22

28 29 30 31               25 26 27 28 29 30         23 24 25 26 27 28 29

                                                    30 31

Примечание. Вместо использования «print» мы можем поочередно использовать функции calendar.prmonth() и calendar.pryear() для печати календарей на месяц и год. Эти функции распечатывают вывод на вашем терминале.

Проверка на високосный год

Мы можем использовать функцию isleap(), чтобы проверить, является ли год високосным или нет. Год передается в качестве аргумента функции, и функция возвращает True, если год високосный, в противном случае возвращает False, если год не високосный. Давайте воспользуемся этой функцией, чтобы увидеть, является ли 2016 год високосным:

calendar.isleap(2016)

Вывод:

True

Количество високосных лет в пределах диапазона

Также можно проверить количество високосных лет в заданном диапазоне лет, указанном в качестве аргумента функции ниже:

calendar.leapdays(year1, year2)

Аргументы, переданные в функцию, – это 2 действительных значения года. Эта функция возвращает количество високосных лет между этими годами.

Пример:

calendar.leapdays(2000, 2017)

Вывод:

5

Как видно, между 2000 и 2017 годами 5 високосных лет, следовательно, результат равен 5.

Возврат дня недели

Метод буднего дня принимает 3 аргумента, а именно: год, месяц и день. Функция возвращает день недели, при этом понедельник имеет индекс 0, а воскресенье – 6. Например:

calendar.weekday(2019, 3, 21)

Вывод:

3

Как видно, эта функция возвращает значение индекса «3», то есть «четверг».

Получение сокращенных названий дней недели

Функция weekheader принимает аргумент n, который указывает количество символов для определенного имени дня недели и возвращает заголовок, содержащий сокращенные имена дней недели.

Например:

print (calendar.weekheader(2))

Вывод:

Mo Tu We Th Fr Sa Su

По аналогии:

print (calendar.weekheader(3))

Вывод:

Mon Tue Wed Thu Fri Sat Sun

Получение количества дней в месяце

Функция monthrange принимает 2 аргумента: год и месяц. Эта функция возвращает кортеж, содержащий индекс дня недели, в который начинается месяц, и количество дней в месяце.

Например:

print (calendar.monthrange(1983, 12))

Вывод:

{3,31}

Поскольку первый день декабря 1983 г. был четвергом, функция возвращает значение индекса четверга в качестве первого элемента кортежа и 31, поскольку это количество дней в декабре.

Получение недели в месяце

Функция monthcalendar принимает 2 аргумента: год и месяц и возвращает матрицу, в которой каждая строка представляет неделю в этом месяце.

Например:

print(calendar.monthcalendar(1983, 11))

Вывод:

[[0,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,19,30,0,0,0]]

Как видите, массив каждой недели начинается с понедельника, а дни вне месяца представлены нулями. Итак, первый массив указывает, что первый день месяца – вторник.

Изменение настроек по умолчанию

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

class calendar.calendar(firstweekday=0)

По умолчанию календари следуют европейскому соглашению, в котором понедельник является первым днем недели, а воскресенье – последним днем недели. Кроме того, месяц январь имеет значение индекса 1, а декабрь – значение индекса 12.

Полезные методы

Ниже приведены некоторые из наиболее полезных методов класса календаря.

iterweekdays()

Этот метод возвращает итератор, содержащий список индексов дней недели.

Например:

import calendar

c = calendar.Calendar()
for i in c.iterweekdays():
    print (i, end=" ")

Вывод:

0 1 2 3 4 5 6

itermonthdates()

Itermonthdates() принимает 2 аргумента: год и месяц. Эта функция возвращает итератор всех дней данного месяца. Кроме того, отображаются все дни до начала месяца и после его окончания, необходимые для получения полной недели.

Пример:

import calendar

c = calendar.Calendar()
for i in c.itermonthdates (2019, 1):
    print (i, end=" ")

Вывод:

2018-12-31 2019-01-01 2019-01-02 2019-01-03 ..............2019-02-03

itermonthdays()

Этот метод похож на метод itermonthdates, но возвращает только номера дней.

Пример:

import calendar

c = calendar.Calendar()
for i in c.itermonthdays (2019, 1):
    print (i, end=" ")

Вывод:

0 1 2 3 4 5 6........ 31 0 0 0

Как видите, все дни до начала месяца и после конца месяца для получения полной недели установлены на «0».

itermonthdays2()

Этот метод отображает кортеж, состоящий из номеров дня и недели.

Пример:

import calendar

c = calendar.Calendar()
for i in c.itermonthdays2 (2019, 1):
    print (i, end=" ")

Вывод:

(0,0) (1,1) (2,2) (3,3) (4,4) (5,5) (6,6) (7,0) (8,1) (9,2) ...........

itermonthdays3()

Этот метод очень похож на метод itermonthdays3(), за исключением того, что он возвращает кортеж из года, месяца и дня месяца.

Пример:

import calendar

c = calendar.Calendar()
for i in c.itermonthdays3 (2019, 1):
    print (i, end=" ")

Вывод:

(2018,12,31) (2019,01,01) (2019,01,02).....(2019,01,31) (2019,02,01) (2019,02,02) (2019,02,03)

monthdatescalendar()

Этот метод принимает в качестве аргументов год и месяц и возвращает список полных недель в месяце. Каждая неделя представляет собой список из 7 объектов datetime.date.

Пример:

import calendar

c = calendar.Calendar()
for i in c.monthdatescalendar (2019, 1):
    print (i, end=" ")

Вывод:

[datetime.date(2018, 12, 31), datetime.date(2019, 01, 01), datetime.date(2019, 01, 02), datetime.date(2019, 01, 03), datetime.date(2019, 01, 04), datetime.date(2019, 01, 05), datetime.date(2019, 01, 06)... datetime.date(2019, 02, 03)]
.....

monthdays2calendar()

Эта функция принимает в качестве аргументов год и месяц и возвращает список недель с каждой неделей в виде 7 кортежей дня месяца и дня недели.

Пример:

import calendar

c = calendar.Calendar()
for i in c.monthdays2calendar (2019, 1):
    print(i, end=" ")

Вывод:

[(0,0) (1,1) (2,2) (3,3) (4,4) (5,5) (6,6)]
[(7,0) (8,1) (9,2) (10,3) (11,4) (12,5) (13,6)]
....

Как видите, первое значение кортежа – это день месяца (0-31), а второе значение кортежа – это номер недели (0-6).

monthdayscalendar()

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

Пример:

import calendar

c = calendar.Calendar()
for i in c.monthdayscalendar(2019, 1):
    print (i, end=" ")

Пример вывода:

[0, 1, 2 , 3, 4, 5, 6] [7, 8, 9, 10, 11, 12, 13]....[28, 29, 30, 31, 0, 0, 0]

yeardatescalendar()

Эта функция принимает год (гггг) и количество месяцев в строке месяца (w). По умолчанию параметр w равен 3. Функция возвращает список строк месяца, где дни – это объекты datetime.date.

Пример:

import calendar

c = calendar.Calendar()
for i in c.yeardatescalendar(2019, 3):
    print (i, end=" ")

Вывод:

[[[datetime.date(2018, 12, 31), datetime.date(2019, 1, 1), datetime.date(2019, 1, 2), datetime.date(2019, 1, 3), datetime.date(2019, 1, 4), datetime.date(2019, 1, 5), datetime.date(2019, 1, 6)], [datetime.date(2019, 1, 7), datetime.date(2019, 1, 8), datetime.date(2019, 1, 9), datetime.date(2019, 1, 10), datetime.date(2019, 1, 11), datetime.date(2019, 1, 12), datetime.date(2019, 1, 13)], [datetime.date(2019, 1, 14), datetime.date(2019, 1, 15), datetime.date(2019, 1, 16), datetime.date(2019, 1, 17), datetime.date(2019, 1, 18), datetime.date(2019, 1, 19), datetime.date(2019, 1, 20)], [datetime.date(2019, 1, 21), datetime.date(2019, 1, 22), datetime.date(2019, 1, 23), datetime.date(2019, 1, 24), datetime.date(2019, 1, 25), datetime.date(2019, 1, 26), datetime.date(2019, 1, 27)], [datetime.date(2019, 1, 28), datetime.date(2019, 1, 29), datetime.date(2019, 1, 30), datetime.date(2019, 1, 31), datetime.date(2019, 2, 1), datetime.date(2019, 2, 2), datetime.date(2019, 2, 3)]] ... ]

yeardays2calendar()

Эта функция принимает год (yyyy) и количество месяцев, которые мы хотим в строке месяца (w). По умолчанию параметр w равен 3. Функция возвращает список недель в виде кортежей дней месяца и дня недели.

Пример:

import calendar

c = calendar.Calendar()
for i in c.yeardays2calendar(2019, 3):
    print (i, end=" ")

Вывод:

[[[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)], [(7, 0), (8, 1), (9, 2), (10, 3), (11, 4), (12, 5), (13, 6)], [(14, 0), (15, 1), (16, 2), (17, 3), (18, 4), (19, 5), (20, 6)], [(21, 0), (22, 1), (23, 2), (24, 3), (25, 4), (26, 5), (27, 6)], [(28, 0), (29, 1), (30, 2), (31, 3), (0, 4), (0, 5), (0, 6)]], [[(0, 0), (0, 1), (0, 2), (0, 3), (1, 4), (2, 5), (3, 6)], [(4, 0), (5, 1), (6, 2), (7, 3), (8, 4), (9, 5), (10, 6)], [(11, 0), (12, 1), (13, 2), (14, 3), (15, 4), (16, 5), (17, 6)], [(18, 0), (19, 1), (20, 2), (21, 3), (22, 4), (23, 5), (24, 6)], [(25, 0), (26, 1), (27, 2), (28, 3), (0, 4), (0, 5), (0, 6)]], [[(0, 0), (0, 1), (0, 2), (0, 3), (1, 4), (2, 5), (3, 6)] ... ]]

yeardayscalendar()

Эта функция принимает год (yyyy) и количество месяцев, которое мы хотим в строке месяца (w). По умолчанию параметр w равен 3. Функция возвращает список недель как день месяца.

Пример:

import calendar

c = calendar.Calendar()
for i in c.yeardayscalendar(2019, 3):
    print (i, end=" ")

Вывод:

[[[0, 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, 0, 0, 0]], [[0, 0, 0, 0, 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, 0, 0, 0]], [[0, 0, 0, 0, 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]]] [[[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, 0, 0, 0, 0, 0]] ... ]]

Класс TextCalendar

TextCalendar используется для создания текстовых календарей, аналогично классу Calendar. Этот класс принимает конструктор, в котором для первого дня недели по умолчанию установлено значение 0. Давайте посмотрим на методы, предоставляемые классом TextCalendar.

formatmonth()

Этот метод принимает 4 аргумента, а именно: год, месяц, столбец ширины дней (w) и количество строк, используемых каждой неделей (l). Этот метод возвращает многострочную строку.

Пример:

import calendar

c = calendar.TextCalendar()
print(c.formatmonth(2019, 1))

Это отображает календарь на январь 2019 года.

Вывод:

    January 2019
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

prmonth()

Этот метод печатает календарь на месяц, возвращенный методом formatmonth. Мы можем использовать эту функцию, чтобы избежать использования функции «print» для печати календаря на терминале.

Чтобы распечатать календарь на январь 2019 года, используйте:

c.prmonth(2019, 1)

formatyear()

Этот метод возвращает календарь в столбце «m» на весь год. В эту функцию передаются следующие аргументы: год (yyyy), ширина столбца даты (w), количество строк в неделю (l), количество пробелов между столбцом месяца (c), количество столбцов (m).

Класс LocaleTextCalendar

Это подкласс класса TextCalendar. Его конструктор принимает дополнительный аргумент locale. Он вернет названия месяца и дня недели в указанном языковом стандарте. Мы можем создать объект текстового календаря на нашем родном языке. Мы можем получить месяц или дни недели или другие данные для отображения календаря, отформатированного из локальной системы, кроме текущего по умолчанию. Пример:

import calendar

for name in calendar.month_name:
    print(name)

Это напечатает название месяцев в соответствии с локальной системой.

Вывод:

January
February
March
April
May
June
July
August
September
October
November
December

Класс HTMLCalendar

Это похоже на класс TextCalendar, но генерирует календарь HTML. В конструкторе этого класса для параметра firstweekday установлено значение «0».

Ниже приведены некоторые методы, предоставляемые классом HTMLCalendar.

formatmonth()

Эта функция отображает календарь на месяц в формате таблицы HTML. Мы можем отобразить календарь на апрель 2019 года в виде таблицы HTML, используя:

hc = calendar.HTMLCalendar()
print(hc.formatmonth(2019, 4))

Вывод:

<table border="0" cellpadding="0" cellspacing="0" class="month">
<tr><th colspan="7" class="month">April 2019</th></tr>
<tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
<tr><td class="mon">1</td><td class="tue">2</td><td class="wed">3</td><td class="thu">4</td><td class="fri">5</td><td class="sat">6</td><td class="sun">7</td></tr>
<tr><td class="mon">8</td><td class="tue">9</td><td class="wed">10</td><td class="thu">11</td><td class="fri">12</td><td class="sat">13</td><td class="sun">14</td></tr>
<tr><td class="mon">15</td><td class="tue">16</td><td class="wed">17</td><td class="thu">18</td><td class="fri">19</td><td class="sat">20</td><td class="sun">21</td></tr>
<tr><td class="mon">22</td><td class="tue">23</td><td class="wed">24</td><td class="thu">25</td><td class="fri">26</td><td class="sat">27</td><td class="sun">28</td></tr>
<tr><td class="mon">29</td><td class="tue">30</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td></tr>
</table>

formatyear()

Этот метод принимает год и количество месяцев в строке (w) в качестве аргументов и печатает календарь всего года в виде таблицы HTML. По умолчанию ширина установлена на 3. Мы можем отобразить календарь на 2019 год в виде таблицы HTML, используя:

hc = calendar.HTMLCalendar()
print(hc.formatyear(2019, 4))

formatyearpage()

Этот метод принимает в качестве аргументов год, количество месяцев в строке (w), каскадную таблицу стилей (CSS) и кодировку. Аргументы css и encoding могут иметь значение None, если мы не используем CSS и кодировку. Эта функция отображает календарь на весь год в виде HTML-страницы с шириной по умолчанию 3. Мы можем распечатать календарь на 2019 год в виде HTML-страницы, используя:

hc = calendar.HTMLCalendar()
print(hc.formatyearpage(2019, 3, css=None, encoding=None))
b'<?xml version="1.0" encoding="utf-8"?>n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">n<html>n<head>n<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />n<title>Calendar for 2019</title>n</head>n<body>n<table border="0" cellpadding="0" cellspacing="0" class="year">n<tr><th colspan="3" class="year">2019</th></tr><tr><td><table border="0" cellpadding="0" cellspacing="0" class="month">n<tr><th colspan="7" class="month">January</th></tr>n<tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>n<tr><td class="noday">nbsp;</td><td class="tue">1</td><td class="wed">2</td><td class="thu">3</td><td class="fri">4</td><td class="sat">5</td><td class="sun">6</td></tr> ... </table></body>n</html>n'

Вывод HTMLCalendar похож на текстовую версию, но заключен в HTML-теги. Ячейка таблицы HTML содержит атрибут класса, соответствующий дню недели. Следовательно, HTML-календарь можно стилизовать с помощью CSS.

Класс LocaleHTMLCalendar

Это подкласс класса HTMLCalendar. Его конструктор принимает дополнительный аргумент locale. Он вернет названия месяцев и дней недели в указанном языковом стандарте в виде таблицы HTML. Мы можем создать объект текстового календаря на нашем родном языке. Например, мы можем сгенерировать календарь на апрель 2019 года в виде таблицы HTML в локали en_AU, используя:

import calendar

cal = calendar.LocaleHTMLCalendar(locale='en_AU.utf8')
print(cal.formatmonth(2019, 4))

Вывод:

<table border="0" cellpadding="0" cellspacing="0" class="month">
<tr><th colspan="7" class="month">April 2019</th></tr>
<tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
<tr><td class="mon">1</td><td class="tue">2</td><td class="wed">3</td><td class="thu">4</td><td class="fri">5</td><td class="sat">6</td><td class="sun">7</td></tr>
<tr><td class="mon">8</td><td class="tue">9</td><td class="wed">10</td><td class="thu">11</td><td class="fri">12</td><td class="sat">13</td><td class="sun">14</td></tr>
<tr><td class="mon">15</td><td class="tue">16</td><td class="wed">17</td><td class="thu">18</td><td class="fri">19</td><td class="sat">20</td><td class="sun">21</td></tr>
<tr><td class="mon">22</td><td class="tue">23</td><td class="wed">24</td><td class="thu">25</td><td class="fri">26</td><td class="sat">27</td><td class="sun">28</td></tr>
<tr><td class="mon">29</td><td class="tue">30</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td><td class="noday">nbsp;</td></tr>
</table>

Заключение

В этом руководстве мы обсудили использование различных классов и подклассов модуля Calendar в Python для работы с датами для управления значениями, ориентированными на неделю, месяц и год. Мы также обсудили использование функций в модуле Calendar. Наряду с этим мы также реализовали классы TextCalendar и HTMLCalendar для создания предварительно отформатированного вывода.

In this tutorial, you will learn how to display a calendar in Python. To display a calendar in Python, we can use an in-built module named calendar. Python calendar module offers many methods to work with dates and calendars.

We can use it to display a whole year calendar, a specific month calendar, or even get the day of a week for a specific date.

Apart from that, we will explore the following Python programs:

  • Display a calendar of a specific year
  • Display a calendar of a specific month
  • Find the name of a month from a number
  • Get current year
  • calendar.weekday() method
  • Get the day of the week for a specific date
  • Calendar in HTML
  • Fetch a specific day for a whole year

Also Read: How To Sort a List of Tuples in Python

Python Program to Display a Calendar of a Specific Year

  • We will first import the Python calendar module using this statement: import calendar
  • After that, we will define the year variable and initialize it with the value whose calendar we would like to display.
  • In this final step, we will use the calendar.calendar(year) function to display the calendar.

Also Read: Arithmetic Operators in Python [With Examples]

Here’s the code for the Python program to display a calendar of a specific year.

Code:

import calendar
year = 3000
print(calendar.calendar(year))

Output:

how to display a calendar in python

Also Read: How to Create Python Empty Set

Calendar of a Specific Month

Now, we will see how to display a calendar of a specific month in Python.

  • Again, we will import the calendar module as we did in the previous example.
  • We will initialize two variables with year and month values.
  • In the final step, we will display the calendar using the calendar.month(year, month) method.

Also Read: Python Matrix Using Numpy [With Examples]

Here’s the Python code to display a calendar of a specific month.

Code:

import calendar
year = 2022
month = 5
print(calendar.month(year, month))

Output:

python program to display month calendar

Also Read: How To Create An Empty Dictionary in Python

Find the Name of a Month From a Number

In this Python program, we will see how to find the name of a month from a number. For example, for the number 6, we should get the name of the sixth month (June) in the output.

  • Import Python calendar module.
  • Use the calendar.month_name[value] to get the month’s name.

Also Read: How to Exit Python Program [4 Methods]

Here’s the code for your reference.

Code:

import calendar
print(calendar.month_name[5])

Output:

get month name from number

Also Read: How to Convert Python Tuples to Lists

Get Current Year

In this example, we will use the datetime Python module to get the current year from the local system.

  • Import datetime module using this statement: import datetime
  • Initialize the CurrentYear variable with the current year’s value using the datetime.datetime.now().year function.
  • Display the CurrentYear variable using the print() statement.

Also Read: How to Handle String Index Out of Range Error In Python

Code:

import datetime
CurrentYear = datetime.datetime.now().year
print("The current year is", CurrentYear)

Output:

get current year in python

Also Read: Python For Loop Index With Examples

Python calendar.weekday() Method

You can use the calendar.weekday(year, month, day) method to get the day of the week. 0 is for Monday, 1 is for Tuesday, and so forth.

  • Import Python calendar module.
  • Initialize the WeekDay variable to get the current weekday using the calendar.weekday(year, month, day) function.
  • Display the current weekday using the print statement.

Also Read: How to Reverse an Array In Python [Flip Array]

Here’s the code for your reference.

Code:

import calendar
WeekDay = calendar.weekday(2022, 5, 11)
print("The current week day is", WeekDay+1)

Output:

calendar weekday function

Also Read: How to Check If Dict Has Key in Python [5 Methods]

Get the Day of the Week for a Specific Date

In this Python example, we will see how to get the day of the week for a specific date. For this, we will use the calendar.weekday function to get the current weekday and then calendar.day_name[argument] to print day of the week.

  • Import calendar Python package.
  • Initialize WeekDayName with calendar.weekday(year, month, day) function to get the current weekday.
  • Print the day of the specific date by using the calendar.day_name[WeekDayName] function.

Also Read: How to Convert Binary to Decimal in Python [5 Methods]

Here’s the code of the Python program to get the day of the week for a specific date.

Code:

import calendar
WeekDayName = calendar.weekday(2022, 5, 11)
print("The day for the specific date is", calendar.day_name[WeekDayName])

Output:

get the day name of specific date in python

Also Read: Python Program To Display Fibonacci Series Up To N Terms

Here we will see how to display an HTML calendar in Python.

  • Import Python calendar module.
  • Initialize CalendarHTML variable using the calendar.HTMLCalendar.
  • Define the CalYear variable and initialize it with the HTML code of a specific calendar year using the CalendarHTML.formatyear(year) method.
  • Print the HTML calendar using the print(CalYear) statement.

Also Read: Python Program To Display Multiplication Table of Any Number

Code:

import calendar

CalendarHTML = calendar.HTMLCalendar()
CalYear = CalendarHTML.formatyear(2022)
print(CalYear)

Output:

display html calendar in python

Also Read: How To Automate Google Search With Python

Fetch a Specific Day for a Whole Year

In this Python calendar example, we will see how to get a specific day for a whole year.

Code:

import calendar

for month in range(1, 13):
    CalYear = calendar.monthcalendar(2022, month)

    FirstWeek = CalYear[0]
    SecondWeek = CalYear[1]

    if FirstWeek[calendar.TUESDAY] != 0:
        InspectionDay = FirstWeek[calendar.TUESDAY]
    else:
        InspectionDay = SecondWeek[calendar.TUESDAY]
    print("%10s %2d" % (calendar.month_name[month], InspectionDay))

Output:

get specific day with whole year

Also Read: 10 Best Udemy Python Courses for Beginners

Summary

In this Python tutorial, we explored how to display a calendar in Python. You also learned how to display an HTML calendar, display a calendar of a specific month, get the current year, and many other examples related to the Python calendar module. Subscribe to our newsletter to receive such articles straight to your inbox.

Himanshu Tyagi

Hello Friends! I am Himanshu, a hobbyist programmer, tech enthusiast, and digital content creator.

With CodeItBro, my mission is to promote coding and help people from non-tech backgrounds to learn this modern-age skill!

Working with date and time data is common and essential for programmers, especially for those engaged in web or android development. So many times, you must have seen calendars on a website or android application, like for selecting your Date of Birth. In python, all these are possible using the python calendar module. If you have worked in Linux, use must be familiar with the ‘cal’ command.

Python calendar module has a calendar class using which we can perform various calculations based on date, month, or year. Not only this, but we also have HTMLCalendar and TextCalendar class that allows us to edit the calendar and use it as per our requirements.  

Syntax of Python Calender

The calendar is a built-in module, so for using it, we just need to import it. To import use – ‘import calendar.’ Many operations can be performed using the calendar module, which we will learn one by one.  

Different Classes of the python calendar module

Calendar (python calendar module)

Calendar class of calendar module creates an object which can be used for formatting. It has only one parameter, firstweekday, whose value by default is set to 0 (‘MONDAY’). For SUNDAY, set the value to 6.  

iterweekdays() It returns the day of the week, which is currently set as the first day. For Monday its ‘0’.
itermonthdates(yearmonth) It returns an iterator, which shows all the days of the month and some days of the previous month and next month which are required to complete the week.
itermonthdays2(yearmonth) It returns an iterator, which gives tuple as output which contains the days of the week from 0-6 with a day of the month.
Sample Output- (16, 3).
itermonthdays3(yearmonth) It is an upgraded version of itermonth2 and returns a tuple containing (year, month, day of the month).
Sample output- (2020, 7, 29)
itermonthdays4(yearmonth) It returns an iterator containing tuple in the given form- (year, month, day of the month, day of the week).
For example- (2020, 7, 21, 1)
monthdays2calendar(yearmonth) It returns a list containing containing tuples in the form (day of the month,day of the week) for the given month of the year.
monthdayscalendar(yearmonth) It returns a list containing the days of the month and some days of previous month and next month completing the week.
yeardays2calendar(year) The output is in the form of a list containing a tuple -(day of the month, day of the week) for the complete specified year.

TextCalendar(firstweekday):

Returns the plain calendar for the whole year, or for a particular month.  

formatmonth(theyearthemonth) Returns a calendar for the given year and month.
formatyear(year) It returns the calendar for the whole year.

HTMLCalendar( firstweekday)

It prints the calendar of a month in HTML format.

Program-

import calendar

cal=calendar.HTMLCalendar(0)
cal.formatmonth(2019,6)
'<table border="0" cellpadding="0" cellspacing="0" class="month">n<tr><th colspan="7" class="month">June 2019</th></tr>n<tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>n<tr><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="sat">1</td><td class="sun">2</td></tr>n<tr><td class="mon">3</td><td class="tue">4</td><td class="wed">5</td><td class="thu">6</td><td class="fri">7</td><td class="sat">8</td><td class="sun">9</td></tr>n<tr><td class="mon">10</td><td class="tue">11</td><td class="wed">12</td><td class="thu">13</td><td class="fri">14</td><td class="sat">15</td><td class="sun">16</td></tr>n<tr><td class="mon">17</td><td class="tue">18</td><td class="wed">19</td><td class="thu">20</td><td class="fri">21</td><td class="sat">22</td><td class="sun">23</td></tr>n<tr><td class="mon">24</td><td class="tue">25</td><td class="wed">26</td><td class="thu">27</td><td class="fri">28</td><td class="sat">29</td><td class="sun">30</td></tr>n</table>n'

Some Common programs using calendar module

Printing a calendar for a particular Year 

Using the calendar class of calendar module, we can print the calendar of any year. 

import calendar
year=int(input()) 
print(calendar.calendar(year))   
2019

python calendar

To print a particular month of a year using python calendar module

year=int(input()) 
month=int(input()) 
print (calendar.month(year,month))  
2020
2
   February 2020
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

In the above two outputs, you must have noticed that the calendar is starting from MONDAY. If we want to change it to any other month, suppose SUNDAY, let us see how we can do that. 

# Using the TextCalendar class
#Storing the TextCalendar object with starting day as Sunday in 'c' variable 
c=calendar.TextCalendar(calendar.SUNDAY)
# Calendar for year 2020
cal=c.formatyear(2020)
print(cal)

To print all the months of a year- 

for i in calendar.month_name: 
    print(i) 
January
February
March
April
May
June
July
August
September
October
November
December

Print (year, month, day of the month, day of the week) 

import calendar
c=calendar.TextCalendar(calendar.SUNDAY)
for i in c.itermonthdays4(2020,7): 
     print(i) 
(2020, 6, 29, 0)
(2020, 6, 30, 1)
(2020, 7, 1, 2)
(2020, 7, 2, 3)
(2020, 7, 3, 4)
(2020, 7, 4, 5)
(2020, 7, 5, 6)
(2020, 7, 6, 0)
(2020, 7, 7, 1)
(2020, 7, 8, 2)
(2020, 7, 9, 3)
(2020, 7, 10, 4)
(2020, 7, 11, 5)
(2020, 7, 12, 6)
(2020, 7, 13, 0)
(2020, 7, 14, 1)
(2020, 7, 15, 2)
(2020, 7, 16, 3)
(2020, 7, 17, 4)
(2020, 7, 18, 5)
(2020, 7, 19, 6)
(2020, 7, 20, 0)
(2020, 7, 21, 1)
(2020, 7, 22, 2)
(2020, 7, 23, 3)
(2020, 7, 24, 4)
(2020, 7, 25, 5)
(2020, 7, 26, 6)
(2020, 7, 27, 0)
(2020, 7, 28, 1)
(2020, 7, 29, 2)
(2020, 7, 30, 3)
(2020, 7, 31, 4)
(2020, 8, 1, 5)
(2020, 8, 2, 6)

Note- It prints (year, month, day of the month, day of the week) for a month and some days of the previous month and next month to complete the weeks. 

To check if a year is a leap year or not using python calendar module

import calendar

def isleapyear(year):
    return calendar.isleap(year)

print(isleapyear(2012))
print(isleapyear(2021))
True 
False

To know how many years are leap years in a range

import calendar
calendar.leapdays(2019,2093)

Output- 

18 

Calendar Without using Python Calendar Module

When I was making this program for you, I took the help of this website to decide which day is the first day of the month keeping everything in check like whether the year is a leap year or not, a number of days in each month, etc.

def firstday(year,month):
    # Refer to the website above for better understanding of the program
    dict1={1:1,2:4,3:4,4:0,5:2,6:5,7:0,8:3,9:6,10:1,11:4,12:6}
    last1=int(str(year)[len(str(year))-2:])
    last=(last1//4)+1
    last=last+dict1[month]
    if isleap(year) and (month==1 or month==2) :
        last=last-1
    else:
        last=last
    if year>=1900 and year<2000:
        last+=0
    elif year>=2000 and year<3000:
        last+=6
    elif year>=1700 and year<1800:
        last+=4
    elif year>=1800 and year<=1900:
        last+=2
    last+=last1
    if last%7==1:
        return 0
    if last%7==2:
        return 1
    if last%7==3:
        return 2
    if last%7==4:
        return 3
    if last%7==5:
        return 4
    if last%7==6:
        return 5
    if last%7==0:
        return 6
def isleap(year):
    if (year % 4) == 0:
        if (year % 100) == 0:
            if (year % 400) == 0:
                return True
            else:
                return False
        else:
            return True
    else:
        return False
def print_calendar(year,month):
    months={1:"January",2:"Feburary",3:"March",4:"April",5:"May",6:"June",7:"July",8:"August",9:"September",10:"October",11:"November",12:"December"}
    print(year,"          ",months[month],"n")
    days_31=[1,3,5,7,8,10,12]
    days_30=[4,6,9,11]
    print("Su  Mo  Tu  We  Th  Fr  Sa")
    day=firstday(year,month)
    
    if month in days_31:
        total_days=31
    elif (month in days_30):
        total_days=30
    else:
        if isleap(year)==True:
            total_days=29
        else:
            total_days=28
    if day!=6:       
        print(" "*(day*4-1),'01',end="")
    elif day==6:       
        print(" "*(day*4-1),'01')
    day+=1
    for i in range(2,total_days+1):
        if i<10:
            i1="0"+str(i)
        else:
            i1=i
        if day%7==0:
            print(i1,end="")
        elif day%7==1:
            print(" ",i1,end="")
        elif day%7==2: 
            print(" ",i1,end="")
        elif day%7==3:
            print(" ",i1,end="")
        elif day%7==4:
            print(" ",i1,end="")
        elif day % 7 ==5:
            print(" ",i1,end="")
        elif day %7==6:
            print(" ",i1)
        day+=1
   
print_calendar(2020,2)
2020            Feburary 

Su  Mo  Tu  We  Th  Fr  Sa
                        01
02  03  04  05  06  07  08
09  10  11  12  13  14  15
16  17  18  19  20  21  22
23  24  25  26  27  28  29

Note- This calendar can only print calendar for years between 1700 and 2100

Printing Holidays for a particular year

For this first you need to install holidays module using pip install holidays.

import holidays 

for holiday in holidays.IND(years = 2020).items(): 
    print(holiday) 
(datetime.date(2020, 1, 14), 'Makar Sankranti / Pongal') (datetime.date(2020, 1, 26), 'Republic Day') (datetime.date(2020, 8, 15), 'Independence Day') (datetime.date(2020, 10, 2), 'Gandhi Jayanti') (datetime.date(2020, 5, 1), 'Labour Day') (datetime.date(2020, 12, 25), 'Christmas')
class Application(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        self.grid()

        year = int(input('nEnter Year eg. 2020n'))
        month = int(input('nEnter month number.n'))
        self.create_widgets(year, month)

    def create_widgets(self, year, month):

        days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
        #create labels
        for i in range(7):
            label = Label(self, text=days[i])
            label.grid(row = 0, column = i)

        weekday, numDays = monthrange(year, month)
        week = 1
        for i in range(1, numDays + 1):
            button = Button(self, text = str(i))
            button.grid(row = week, column = weekday)

            weekday += 1
            if weekday > 6:
                week += 1
                weekday = 0


root=Tk()
obj = Application(root)
root.mainloop()

python calendar

For printing a calendar for specific locale-

import calendar
cal = calendar.LocaleTextCalendar(locale='en_IN')
print(cal.formatmonth(2020, 9))

Output-

   September 2020
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

Must Read:

  • How to Convert String to Lowercase in
  • How to Calculate Square Root
  • User Input | Input () Function | Keyboard Input
  • Best Book to Learn Python

Conclusion

There are many more functions in the python calendar module. We have given you a brief idea about the classes and how basic things can be done. You can try many different things on your own to understand the module better.

Try to run the programs on your side and let us know if you have any queries.

Happy Coding!

Понравилась статья? Поделить с друзьями:

Не пропустите и эти статьи:

  • Как мало пройдено дорог как много сделано ошибок кто написал
  • Как написать как я провела день
  • Как написать календарь на javascript
  • Как латиницей написать александрович
  • Как написать как у тебя дела на английском

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии