Работа с датой и временем. Часть II

Больше модулей для работы с временем и датой, измерение времени выполнения программы

Модуль time

Для использования: import time

В Python помимо встроенного модуля datetime есть еще модуль time, который обычно используется для работы с текущим временем.

Его работа основывается на общепринятой системе описания времени. Согласно ее концепции, текущее время представляется в виде обыкновенного вещественного значения в секундах, прошедших с момента начала эпохи (полночь 1 января 1970 года) и до сегодняшнего дня.

Возможности модуля:

  • отображает информацию о времени, прошедшем с начала эпохи
  • преобразовывает значение системного времени в удобный вид
  • прерывает выполнение программы на заданное количество секунд
  • измеряет время выполнения программы или её отдельных модулей
Инфо
datetime.time и модуль time – не одно и то же!

Функция time()

Возвращает количество секунд, прошедших с начала эпохи:

1
2
3
4
5
6
import time

seconds = time.time()  # получаем количество прошедших секунд в виде float числа
print('Количество секунд с начала эпохи =', seconds)

# Вывод: Количество секунд с начала эпохи = 1630387918.354396

Функция ctime()

Для того чтобы получить текущую дату в более удобном для человека виде, нужно использовать функцию ctime(), которая принимает в качестве аргумента количество секунд, прошедших с начала эпохи, и возвращает строку, представляющую собой локальное время:

1
2
3
4
5
6
7
import time

local_time = time.ctime(time.time())  # аналогично local_time = time.ctime()

print(local_time)

# Вывод: текущая дата и время на вашем пк
Инфо
Если вызвать ctime() без аргументов, результат будет аналогичным

Функция sleep()

Используется для добавления задержки в выполнение программы. В качестве аргумента принимает количество секунд (secs) – задержка в секундах. secs может быть как int, так и float

1
2
3
4
5
import time 

print('Before the sleep statement')
time.sleep(3)
print('After the sleep statement')
Инфо
Функция sleep() нередко используется для тестирования кода и намеренного внесения задержек на различных этапах выполнения программы

Измерение времени выполнения программы

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

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

start_time = time.time()

for i in range(5): 
    time.sleep(1)

end_time = time.time()

elapsed_time = end_time - start_time
print(f'Время работы программы = {elapsed_time}')

# Вывод: Время работы программы = 5.022884845733643

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

Инфо
Бывает так, что очередной вызов функции time() вернет значение меньше, чем значение, полученное при предыдущем вызове.

Функция monotonic()

Для измерения времени выполнения программы идеально подходит функция monotonic(), так как ее результат не зависит от корректировки системных часов и других внешних условий.

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

start_time = time.monotonic()

for i in range(5):
    time.sleep(1)

end_time = time.monotonic()

elapsed_time = end_time - start_time
print(f'Время работы программы = {elapsed_time}')

# Вывод: Время работы программы = 5.0

Функция perf_counter()

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

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

start_time = time.perf_counter()

for i in range(5):
    time.sleep(1)

end_time = time.perf_counter()

elapsed_time = end_time - start_time
print(f'Время работы программы = {elapsed_time}')

# Вывод: Время работы программы = 5.042140900040977

Замечания

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

  • По сравнению с собственными реализациями, функция factorial() из модуля math выполняется быстрее, так как реализована на языке C.
  • Списочные выражения (или же list comprehensions) выполняются быстрее, чем использование цикла for на пару с методом append.
  • В случае если требуется создать список на основе итерируемого объекта или коллекции без какого-либо изменения элементов, то лучшим вариантом будет функция list().

Тип данных struct_time

Единственный тип данных, который имеется в модуле timestruct_time. Он представляет собой именованный кортеж, содержащий информацию о времени. Структура представления времени struct_time чем-то похожа на уже изученный тип datetime.

Сделать
Именованные кортежи будут описаны подробнее в следующих конспектах

Именованный кортеж struct_time состоит из следующих атрибутов:

Номер индексаАтрибутЗначение
0tm_yearдиапазон от 0000 до 9999
1tm_monдиапазон от 1 до 12
2tm_mdayдиапазон от 1 до 31
3tm_hourдиапазон от 0 до 23
4tm_minдиапазон от 0 до 59
5tm_secдиапазон от 0 до 61 (високосная секунда)
6tm_wdayдиапазон от 0 до 6, понедельник=0
7tm_ydayдиапазон от 1 до 366
8tm_isdstзначения -1, 0, 1
N/Atm_zoneсокращение названия часового пояса
N/Atm_gmtoffсмещение к востоку от UTC в секундах

Создавать объекты типа struct_time можно на основе кортежа:

1
2
3
4
import time

time_tuple = (2021, 8, 31, 5, 31, 58, 1, 243, 0)
time_obj = time.struct_time(time_tuple)

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

Функция localtime()

localtime() принимает в качестве аргумента количество секунд, прошедших с начала эпохи, и возвращает кортеж struct_time в локальном времени.

Инфо
Если функции localtime() передан аргумент None, вернется значение time()
1
2
3
4
5
6
7
8
import time

result = time.localtime(1630387918)
print('Результат:', result)
print('Год:', result.tm_year)
print('Месяц:', result.tm_mon)
print('День:', result.tm_mday)
print('Час:', result.tm_hour)
1
2
3
4
5
6
# Вывод:
Результат: time.struct_time(tm_year=2021, tm_mon=8, tm_mday=31, tm_hour=8, tm_min=31, tm_sec=58, tm_wday=1, tm_yday=243, tm_isdst=0)
Год: 2021
Месяц: 8
День: 31
Час: 8

Также мы могли бы обращаться к данным именованного кортежа по индексам. К примеру, print('Год:', result[0]), вывел бы ту же строку, что и print('Год:', result.tm_year) в коде выше.


Функция gmtime()

gmtime() принимает в качестве аргумента количество секунд, прошедших с начала эпохи, и возвращает кортеж struct_time в UTC.

Инфо
Если функции gmtime() передан аргумент None, также вернется значение time()

Функция mktime()

mktime() принимает struct_time (или кортеж, содержащий 9 значений, относящихся к этому типу) в качестве аргумента и возвращает количество секунд, прошедших с начала эпохи, в местном времени.

1
2
3
4
5
6
7
import time

time_tuple = (2021, 8, 31, 5, 31, 58, 1, 243, 0)
time_obj = time.mktime(time_tuple)
print('Локальное время в секундах:', time_obj)

# Вывод: Локальное время в секундах: 1630377118.0

Функция mktime() является обратной к функции localtime(). Посмотрим на пример этой связи:

1
2
3
4
5
6
7
8
9
import time

seconds = 1630377118

time_obj = time.localtime(seconds)    # возвращает struct_time
print(time_obj)

time_seconds = time.mktime(time_obj)  # возвращает секунды из struct_time
print(time_seconds)
1
2
3
# Вывод:
time.struct_time(tm_year=2021, tm_mon=8, tm_mday=31, tm_hour=5, tm_min=31, tm_sec=58, tm_wday=1, tm_yday=243, tm_isdst=0)
1630377118.0
Опасность
Если кортеж с неправильной длиной или имеющий элементы неправильного типа передаётся функции, ожидающей struct_time, возникает ошибка TypeError!

Функция asctime()

asctime() принимает struct_time (или кортеж, содержащий 9 значений, относящихся к этому типу) в качестве аргумента и возвращает строку, представляющую собой дату и время.

1
2
3
4
5
6
7
8
import time

time_tuple = (2021, 8, 31, 5, 31, 58, 1, 243, 0)

result = time.asctime(time_tuple)
print('Результат:', result)

# Вывод: Результат: Tue Aug 31 05:31:58 2021

Форматированный вывод

Функции ctime() и asctime() имеют практически одинаковый функционал, за тем исключением, что первая функция принимает количество прошедших от начала эпохи секунд, а вторая принимает struct_time (или соответствующий кортеж). Обе функции представляют время в более удобном виде, благодаря автоматическому форматированию. Однако, автоматическое форматирование не всегда то, что нужно, поскольку может показаться чересчур сложным для восприятия, либо же недостаточно информативным. Именно поэтому функции strftime() и strptime() модуля time позволяют создавать свои уникальные типы форматирования.

  • strftime() принимает строку с некоторым набором правил для форматирования и объект struct_time (или соответствующий кортеж) в качестве аргументов и возвращает строку с датой в зависимости от использованного формата:
1
2
3
4
5
6
7
import time

time_obj = time.localtime()
result = time.strftime('%d.%m.%Y, %H:%M:%S', time_obj)
print(result)

# Вывод: 01.09.2021, 08:50:32
  • strptime() делает разбор строки в зависимости от использованного формата и возвращает объект struct_time:
1
2
3
4
5
6
7
import time

time_string = '1 September, 2021'
result = time.strptime(time_string, '%d %B, %Y')
print(result)

# Вывод: time.struct_time(tm_year=2021, tm_mon=9, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=244, tm_isdst=-1)
Опасность
При этом строка time_string должна полностью соответствовать формату %d %B, %Y, в противном случае возникнет исключение ValueError!

Модуль calendar

Для использования: import calendar

По умолчанию модуль calendar следует григорианскому календарю, где понедельник является первым днём недели (номер 0), а воскресенье – последним (номер 6). В отличии от предыдущих модулей date и time, которые также предоставляют функции, связанные с календарём, модуль calendar предоставляет основные функции, связанные с отображением и манипулированием календарями.

Атрибуты calendar

  • Атрибут calendar.day_name возвращает итерируемый объект, содержащий названия дней недели на английском языке:
1
2
3
4
import calendar

for name in calendar.day_name:
    print(name)
1
2
3
4
5
6
7
8
# Вывод:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
  • Атрибут calendar.day_abbr возвращает итерируемый объект, содержащий сокращенные названия дней недели:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import calendar, locale

for name in calendar.day_abbr:
    print(name, end=' ')

locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')

print()
for name in calendar.day_abbr:
    print(name, end=' ')
1
2
3
# Вывод:
Mon Tue Wed Thu Fri Sat Sun
Пн Вт Ср Чт Пт Сб Вс
  • Атрибут calendar.month_name возвращает итерируемый объект, содержащий названия месяцев года:
1
2
3
4
5
6
7
8
9
import calendar, locale

english_names = list(calendar.month_name)
print(english_names)

locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')

russian_names = list(calendar.month_name)
print(russian_names)
1
2
3
# Вывод:
['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
['', 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']
Инфо
Атрибут month_name соответствует обычному соглашению, что январь – это месяц номер 1, поэтому список имеет длину в 13 элементов, первый из которых – пустая строка
  • Атрибут calendar.month_abbr возвращает итерируемый объект, содержащий сокращенные названия месяцев года:
1
2
3
4
5
6
7
8
9
import calendar, locale

english_names = list(calendar.month_abbr)
print(english_names)

locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')

russian_names = list(calendar.month_abbr)
print(russian_names)
1
2
3
# Вывод:
['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
['', 'янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек']
Инфо
Объекты, доступные по атрибутам day_name, day_abbr, month_name и month_abbr, поддерживают индексацию
  • Для получения номеров дней недели можно использовать атрибуты: MONDAY, TUESDAY, ..., SUNDAY. К примеру, print(calendar.MONDAY) выведет 0.

Функции calendar

  • Функция setfirstweekday() устанавливает заданный день недели в качестве начала недели. Например, чтобы установить первый будний день воскресенье, мы используем код:
1
2
3
import calendar

calendar.setfirstweekday(calendar.SUNDAY)
  • Функция firstweekday() возвращает целое число, означающее день недели, установленное в качестве начала недели:
1
2
3
4
5
import calendar

print(calendar.firstweekday())
calendar.setfirstweekday(calendar.SUNDAY)
print(calendar.firstweekday())
1
2
3
# Вывод:
0
6
  • Функция isleap() возвращает True, если год високосен, иначе – False.

  • Функция leapdays(y1, y2) возвращает количество високосных лет в диапазоне от y1 до y2 (не включая), где y1 и y2 – годы:

1
2
3
4
5
import calendar

print(calendar.leapdays(2020, 2025))

# Вывод: 2
  • Функция weekday(year, month, day) возвращает день недели в виде целого числа (где 0 – понедельник, 6 – воскресенье) для заданной даты. Аргументы функции year – год начиная с 1970, month – месяц в диапазоне 1-12, day – число в диапазоне 1-31:
1
2
3
4
import calendar

print(calendar.weekday(2021, 9, 1))  # среда
print(calendar.weekday(2021, 9, 2))  # четверг
1
2
3
# Вывод:
2
3
  • Функция monthrange(year, month) возвращает день недели первого дня месяца и количество дней в месяце в виде кортежа для указанного года year и месяца month
1
2
3
4
import calendar

print(calendar.monthrange(2022, 1))  # январь 2022 года
print(calendar.monthrange(2021, 9))  # сентябрь 2021 года
1
2
3
# Вывод:
(5, 31)
(2, 30)
  • Функция monthcalendar(year, month) возвращает матрицу, представляющую календарь на месяц. Каждая строка матрицы представляет неделю:
1
2
3
import calendar

print(*calendar.monthcalendar(2021, 9), sep='\n')
1
2
3
4
5
6
# Вывод:
[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, 0, 0, 0]
Инфо
Дни, которые не входят в указанный месяц, представлены нулями. При этом каждая неделя начинается с понедельника, если не установлено другое функцией ​​setfirstweekday()
  • Функция month(year, month, w=0, l=0) возвращает календарь на месяц в многострочной строке. Аргументами функции являются: year (год), month (месяц), w (ширина столбца даты) и l (количество строк, отводимые на неделю).
Инфо
Аргументы w и l имеют значения по умолчанию, поэтому их можно не передавать явно при вызове функции
1
2
3
4
5
6
7
import calendar

print(calendar.month(2021, 9))
print(calendar.month(2021, 10))
print(calendar.month(2021, 9, w=3))
print(calendar.month(2021, 9, l=2))
print(calendar.month(2021, 9, w=5, l=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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Вывод:
   September 2021
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

    October 2021
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

       September 2021
Mon Tue Wed Thu Fri Sat Sun
          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

   September 2021

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


              September 2021

 Mon   Tue   Wed   Thu   Fri   Sat   Sun

               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
  • Функция calendar(year, w=2, l=1, c=6, m=3) возвращает календарь на весь год в виде многострочной строки. Аргументами функции являются: year (год), w (ширина столбца даты), l (количество строк, отводимые на неделю), c (количество пробелов между столбцом месяца) и m (количество столбцов).
Инфо
Аргументы w, l, c, m имеют значения по умолчанию, поэтому их можно не передавать явно при вызове функции
1
2
3
import calendar

print(calendar.calendar(2021))
 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
35
36
# Вывод:
                                  2021

      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       1  2  3  4  5  6  7       1  2  3  4  5  6  7
 4  5  6  7  8  9 10       8  9 10 11 12 13 14       8  9 10 11 12 13 14
11 12 13 14 15 16 17      15 16 17 18 19 20 21      15 16 17 18 19 20 21
18 19 20 21 22 23 24      22 23 24 25 26 27 28      22 23 24 25 26 27 28
25 26 27 28 29 30 31                                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                      1  2          1  2  3  4  5  6
 5  6  7  8  9 10 11       3  4  5  6  7  8  9       7  8  9 10 11 12 13
12 13 14 15 16 17 18      10 11 12 13 14 15 16      14 15 16 17 18 19 20
19 20 21 22 23 24 25      17 18 19 20 21 22 23      21 22 23 24 25 26 27
26 27 28 29 30            24 25 26 27 28 29 30      28 29 30
                          31

        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                         1             1  2  3  4  5
 5  6  7  8  9 10 11       2  3  4  5  6  7  8       6  7  8  9 10 11 12
12 13 14 15 16 17 18       9 10 11 12 13 14 15      13 14 15 16 17 18 19
19 20 21 22 23 24 25      16 17 18 19 20 21 22      20 21 22 23 24 25 26
26 27 28 29 30 31         23 24 25 26 27 28 29      27 28 29 30
                          30 31

      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       1  2  3  4  5  6  7             1  2  3  4  5
 4  5  6  7  8  9 10       8  9 10 11 12 13 14       6  7  8  9 10 11 12
11 12 13 14 15 16 17      15 16 17 18 19 20 21      13 14 15 16 17 18 19
18 19 20 21 22 23 24      22 23 24 25 26 27 28      20 21 22 23 24 25 26
25 26 27 28 29 30 31      29 30                     27 28 29 30 31
  • Функция prmonth(theyear, themonth, w=0, l=0) печатает календарь на месяц, возвращенный функцией month(theyear, themonth, w=0, l=0).

Функция prcal(year, w=0, l=0, c=6, m=3) печатает календарь на весь год, возвращенный функцией calendar(year, w=0, l=0, c=6, m=3)

Следующие два блока кода эквиваленты:

1
2
3
4
import calendar

calendar.prmonth(2021, 9)
calendar.prcal(2021)
1
2
3
4
import calendar

print(calendar.month(2021, 9))
print(calendar.calendar(2021))

Они выводят:

 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
35
36
37
38
39
40
41
42
   September 2021
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
                                  2021

      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       1  2  3  4  5  6  7       1  2  3  4  5  6  7
 4  5  6  7  8  9 10       8  9 10 11 12 13 14       8  9 10 11 12 13 14
11 12 13 14 15 16 17      15 16 17 18 19 20 21      15 16 17 18 19 20 21
18 19 20 21 22 23 24      22 23 24 25 26 27 28      22 23 24 25 26 27 28
25 26 27 28 29 30 31                                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                      1  2          1  2  3  4  5  6
 5  6  7  8  9 10 11       3  4  5  6  7  8  9       7  8  9 10 11 12 13
12 13 14 15 16 17 18      10 11 12 13 14 15 16      14 15 16 17 18 19 20
19 20 21 22 23 24 25      17 18 19 20 21 22 23      21 22 23 24 25 26 27
26 27 28 29 30            24 25 26 27 28 29 30      28 29 30
                          31

        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                         1             1  2  3  4  5
 5  6  7  8  9 10 11       2  3  4  5  6  7  8       6  7  8  9 10 11 12
12 13 14 15 16 17 18       9 10 11 12 13 14 15      13 14 15 16 17 18 19
19 20 21 22 23 24 25      16 17 18 19 20 21 22      20 21 22 23 24 25 26
26 27 28 29 30 31         23 24 25 26 27 28 29      27 28 29 30
                          30 31

      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       1  2  3  4  5  6  7             1  2  3  4  5
 4  5  6  7  8  9 10       8  9 10 11 12 13 14       6  7  8  9 10 11 12
11 12 13 14 15 16 17      15 16 17 18 19 20 21      13 14 15 16 17 18 19
18 19 20 21 22 23 24      22 23 24 25 26 27 28      20 21 22 23 24 25 26
25 26 27 28 29 30 31      29 30                     27 28 29 30 31
Поддержать автора
NoisyCake cloudtipscloudtips
0%