Введение
Работа программиста со временем и датой зачастую связана со многими сложностями. Дело в том, что существует множество форматов представления таких данных. Они зависят от локализации (местоположения), предпочтения тех, кто генерирует эти данные и много-много ещё от чего. В итоге, выполняя простейшие для повседневной жизни операции, программист может столкнуться с целым набором сложностей. К счастью, в языке Python есть встроенный модуль под названием datetime. Этот модуль призван максимально упростить данный класс задач. Давайте знакомиться!
Применение
Модуль datetime применяется в Пайтоне для операций с датами и временем и стремится сделать это оптимальным способом.
Этот модуль включает в себя различные классы, методы которых позволяют:
Узнать сколько сейчас времени и какая дата.
Выполнить манипуляции с датами, такие, например, как вычисление промежутка времени.
Выполнить манипуляции со временем, такие, например, как сравнение двух моментов времени.
Менять формат представления времени и даты.
Номер года, который допускает модуль, лежат внутри интервала от 1 до 9999
Для начала использования данного модуля Вам необходимо импортировать его в Ваш код:
import datetime
Отличие datetime от time
В стандартной библиотеке Питона есть ещё один модуль: time. Он тоже предназначен для работы со временем. В чём их отличие? Разница в том, что модуль time главным образом предназначен для работы с метками времени Unix (выражается в виде числа с плавающей запятой, считающегося секундами с эпохи Unix). datetime модуль может поддерживать многие из тех же операций, но обеспечивает более объектно-ориентированный набор типов, а также имеет некоторую ограниченную поддержку часовых поясов.
Классы библиотеки
Как мы уже упоминали, библиотека datetime состоит из нескольких классов, которые перечислены в следующей таблице:
Метод Описание
date позволяет манипулировать датами независимо от времени (месяц, день, год)
time позволяет управлять временем независимо от даты (час, минута, секунда, микросекунда)
datetime позволяет нам управлять временем и датами вместе (месяц, день, год, час, секунда, микросекунда)
timedelta продолжительность времени, используемого для управления датами и измерения
tzinfo абстрактный класс для работы с часовыми поясами
timezone абстрактный базовый класс как фиксированное смещение от UTC
date
Класс date применяется для отображения даты, состоящей из года, месяца и числа.
Объект, порождаемый этим классом, является датой (год, месяц и день) по Григорианскому календарю.
1 января года 1 будет иметь №1, 2 января года 1 — №2 и так далее.
Каждый параметр должен быть целым числом в определённых диапазонах:
1 <= год <= 9999
1 <= месяц <= 12
1 <= день <= количество дней в данном месяце и году
Если указан аргумент за пределами этих диапазонов, интерпретатор вернёт ошибку ValueError.
import datetime
today_date = datetime.date(2021, 7, 22)
print(today_date)
print(type(today_date))
print('Или так:')
norbert_birthday = datetime.date(year=1894, month=11, day=26)
print(norbert_birthday)
# Вывод:
2021-07-22
<class 'datetime.date'>
Или так:
1894-11-26
Для возврата сегодняшней локальной даты используется функция класса date today (). Функция today () имеет несколько атрибутов (год, месяц и день).
import datetime
today_date = datetime.date.today()
print(today_date)
# Вывод:
2021-07-22
Атрибуты даты можно вывести по отдельности:
import datetime
today_date = datetime.date.today()
print('Год:', today_date.year, end=' ')
print('Месяц:', today_date.month, end=' ')
print('День:', today_date.day, end='')
# Вывод:
Год: 2021 Месяц: 7 День: 22
Однако, стоит помнить, что у уже созданного объекта изменить атрибуты не получится:
import datetime
today_date = datetime.date(2021, 7, 22)
today_date.year += 1
print(today_date)
# Вывод:
Traceback (most recent call last):
File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.1\scratches\scratch.py", line 4, in
today_date.year += 1
AttributeError: attribute 'year' of 'datetime.date' objects is not writable
Process finished with exit code 1
time
Класс time предназначен для отображения времени без использования даты. Создаётся объект этого класса так же, как и date, но со своими параметрами. Все аргументы необязательны. Аргумент tzinfo может иметь тип None или быть экземпляром класса tzinfo. Остальные аргументы должны быть целыми числами в следующих диапазонах:
• 0 <= час < 24,
• 0 <= минута < 60,
• 0 <= секунда < 60,
• 0 <= микросекунда < 1000000,
Когда передаётся значение параметра, лежащее вне этих диапазонов, интерпретатор возвращает ошибку ValueError. Все аргументы имеют значение по умолчанию 0, кроме tzinfo, которое по умолчанию None. Вот пример, использующий данный класс:
from datetime import time
a = time()
print("a =", a)
b = time(00, 1, 1)
print("b =", b)
c = time(hour = 00, minute = 1, second = 1)
print("c =", c)
d = time(12, 16, 13, 566234)
print("d =", d)
# Вывод:
a = 00:00:00
b = 00:01:01
c = 00:01:01
d = 12:16:13.566234
Аналогично классу date, после создания time объекта вы можете легко распечатать его атрибуты, такие как час, минута и т.п.
from datetime import time
a = time(12, 16, 17)
print("Часы:", a.hour)
print("Минуты:", a.minute)
print("Секунды:", a.second)
print("Микросекунды:", a.microsecond)
# Вывод:
Часы: 12
Минуты: 16
Секунды: 17
Микросекунды: 0
Обратите внимание, что мы не указывали аргумент микросекунды. Следовательно, печатается его значение по умолчанию, равное нулю.
datetime
В datetime модуле есть класс с именем datetime, который может содержать информацию как из объектов даты, так и из объектов времени.
from datetime import datetime
today_date = datetime(2021, 7, 22)
print(today_date)
random_date = datetime(1999, 11, 28, 23, 55, 59, 342380)
print(random_date)
# Вывод:
2021-07-22 00:00:00
1999-11-28 23:55:59.342380
Первые три аргумента (год, месяц и день) в datetime() конструкторе обязательны:
from datetime import datetime
today_month = datetime(2021, 7)
print(today_month)
# Вывод:
Traceback (most recent call last):
File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.1\scratches\scratch.py", line 3, in
today_month = datetime(2021, 7)
TypeError: function missing required argument 'day' (pos 3)
Process finished with exit code 1
Получить настоящий момент времени можно используя методы, один из которых уже использовался ранее в date. Следующий код иллюстрирует вызов методов today и now, возвращающих в Питон текущую дату и время:
import datetime
today_date = datetime.datetime.today()
time_now = datetime.datetime.now()
print('Сегодня:', today_date)
print('Сейчас:', time_now)
# Вывод:
Сегодня: 2021-07-22 16:26:25.224837
Сейчас: 2021-07-22 16:26:25.224836
Если Вам не подходит тот формат, в котором данные отображаются по умолчанию, Вы можете воспользоваться методом strftime().
Метод strftime() создает отформатированную строку из заданного объекта date, datetime или time. Он принимает различные идентификаторы формата как параметры и меняет на их основании строковое представление.
Форматирование даты с помощью strftime():
from datetime import datetime
now = datetime.now()
t = now.strftime("%H:%M:%S")
print("Первая строка:", t)
s1 = now.strftime("%m/%d/%Y, %H:%M:%S, %A %B %Y")
print("Вторая строка:", s1)
s2 = now.strftime("%a %b %y, %d/%m/%Y, %H:%M:%S")
print("Третья строка:", s2)
# Вывод:
Первая строка: 08:27:45
Вторая строка: 07/23/2021, 08:27:45, Friday July 2021
Третья строка: Fri Jul 21, 23/07/2021, 08:27:45
Здесь %Y, %m, %d, и т.д. являются кодами формата strftime() Метод принимает один или несколько кодов формата. В таблице ниже показаны коды, которые можно передавать в strftime():
Код | Описание | Пример |
---|---|---|
%a | Сокращенное название дня недели. | Fri |
%A | Полное название дня недели. | Friday |
%w | День недели в виде десятичного числа. | 0, 1, …, 6 |
%d | День месяца. | 23 |
%b | Сокращенное название месяца. | Jul |
%B | Полное название месяца. | July |
%m | Месяц как десятичное число с нулями. | 01, 02, …, 12 |
%y | Год без века как десятичное число с нулями. | 21 |
%Y | Год с веком в виде десятичного числа. | 2021 |
%H | Час (в 24-часовом формате) как десятичное число с нулями. | 00, 01, …, 23 |
%I | Час (12-часовой формат) в виде десятичного числа с нулями. | 01, 02, …, 12 |
%p | Локаль AM или PM. | AM |
%M | Минута в виде десятичного числа с нулями. | 00, 01, …, 59 |
%S | Секунды как десятичное число с нулями. | 00, 01, …, 59 |
%f | Микросекунды в виде десятичного числа с нулями слева. | 000000–999999 |
%z | Смещение UTC. | +0000, -0400, +1030 |
%Z | Название часового пояса. | UTC, GMT |
%j | День года в виде десятичного числа с нулями. | 001, 002, …, 366 |
%U | Номер недели в году (воскресенье как первый день недели). Все дни нового года, предшествующие первому воскресенью, считаются нулевой неделей. | 00, 01, …, 53 |
%W | Номер недели в году (понедельник как первый день недели). Все дни нового года, предшествующие первому понедельнику, считаются нулевой неделей. | 00, 01, …, 53 |
%c | Соответствующее представление даты и времени местного стандарта. | Fri Jul 23 08:37:50 2021 |
%x | Соответствующее представление даты местного стандарта. | 07/23/21 |
%X | Соответствующее представление времени местного стандарта. | 08:42:41 |
%% | Буквальный символ «%». | % |
Как и в случае с time и date, в классе datetime можно обратиться к конкретной составляющей объекта:
import datetime
now = datetime.datetime.now()
print('Сейчас')
print('Год:', now.year)
print('Месяц:', now.month)
print('День:', now.day)
print('Часов:', now.hour)
print('Минут:', now.minute)
print('Секунд', now.second)
print('Микросекунд:', now.microsecond)
# Вывод:
Сейчас
Год: 2021
Месяц: 7
День: 23
Часов: 8
Минут: 48
Секунд 23
Микросекунд: 695403
Сформировать новый объект типа datetime можно и с помощью двух разных объектов, представляющих время и дату (time и date). Для этого используется функция combine. В следующем примере показывается как переменные a и b получают некоторые значения, после чего передаются методу combine в качестве двух параметров.
from datetime import datetime, date, time
today_date = date(2021, 7, 23)
time_now = time(8, 48, 23)
today_datetime = datetime.combine(today_date, time_now)
print(today_datetime)
# Вывод:
2021-07-23 08:48:23
Другие функции класса datetime:
Метод Описание
utcnow () текущая дата и время в формате UTC
fromtimestamp() местная дата и время, соответствующие метке времени POSIX
utcfromtimestamp() дата и время в формате UTC, соответствующее метке времени POSIX
fromordinal() дата и время, соответствующее Григорианскому порядковому номеру, где 1 января 1 года имеет порядковый номер 1
combine() возвращает новый объект datetime, компоненты даты которого равны заданному объекту даты и времени
fromisoformat() возвращает datetime.time(), который соответствует строке time_string в одном из форматов, возвращаемых методом time.isoformat()
Операции
Пользуясь классом datetime, можно легко находить разницу между двумя разными датами. Следующим пример демонстрирует создание двух объектов:
from datetime import datetime
today_date = datetime.now()
random_date = datetime(1989, 9, 21)
delta = today_date - random_date
print(delta.days)
print(delta.seconds)
print(delta.microseconds)
# Вывод:
11628
32213
845546
Перечень доступных операций, с которыми можно работать, располагается в следующей таблице:
Операция | Значение |
---|---|
a + b | суммирует значения дат a и b |
a – b | находит разницу между датами a и b |
a * i | умножает численное представление свойств даты a на некую константу i |
a // i | делит численное представление свойств даты a на некую константу i, остаток отбрасывается |
+a | возвращает объект timedelta с полностью идентичным значением a |
–a | возвращает объект timedelta с полностью противоположным значением a |
a > b | возвращает true, если a больше b |
a < b | возвращает true, если a меньше b |
abs(a) | возвращает объект timedelta с положительным значением всех свойств a |
str(a) | возвращает строковое представление объекта a в формате, заданном по умолчанию |
repr(a) | возвращает строковое представление объекта a в формате с отрицательными значениями |
timedelta
Метод timedelta предназначен для вычисления различий в датах. Это один из самых простых способов манипулировать датой.
Мы можем создать объект timedelta, используя конструктор его класса.
from datetime import timedelta
timedelta_object = timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
print(timedelta_object)
zero_obj = timedelta()
print(zero_obj)
# Вывод:
0:00:00
0:00:00
Обратите внимание, что мы можем настроить параметры для создания нашего собственного объекта datetime. Если вы не устанавливаете значение аргумента, по умолчанию принимается 0. Аргументы могут быть целыми или плавающими, а также положительными или отрицательными.
Помимо создания наших собственных объектов timedelta, мы также можем манипулировать существующими объектами timedelta.
Мы можем складывать, вычитать или делить два объекта timedelta с помощью основных операторов.
from datetime import timedelta
timedelta_object = timedelta(hours=10, seconds=10)
print('timedelta_object:', timedelta_object)
new_timedelta_object = timedelta(hours=5, seconds=25)
print('new_timedelta_object:', new_timedelta_object)
print('Операции:')
print('Сложение:', timedelta_object + new_timedelta_object, 'Вычитание:', timedelta_object - new_timedelta_object, 'Деление:', timedelta_object / new_timedelta_object, sep='\n')
# Вывод:
timedelta_object: 10:00:10
new_timedelta_object: 5:00:25
Операции:
Сложение:
15:00:35
Вычитание:
4:59:45
Деление:
1.9977808599167823
tzinfo и timezone
Классы tzinfo и timezone применяются для работы с информацией, которая содержит сведения о часовых поясах. Создать объект, принадлежащий типу tzinfo невозможно, поскольку этот класс является абстрактным. Однако можно воспользоваться наследованием, создав собственный класс на основе tzinfo. При этом следует помнить, что для работы с такими объектами придется реализовать несколько абстрактных методов, к числу которых относятся utcoffset (смещение по местному времени с UTC), dst (настройка перехода на летнее время), а также функция tzname (имя часового пояса в виде строки).
from datetime import tzinfo, timedelta, datetime, timezone
class UTC(tzinfo):
def __init__(self, offset=18801, name=None):
self.offset = timedelta(seconds=offset)
self.name = name or self.__class__.__name__
def utcoffset(self, dt):
return self.offset
def tzname(self, dt):
return self.name
def dst(self, dt):
return timedelta(0)
now = datetime.now(timezone.utc)
print(now)
b = datetime.now(UTC())
print(b)
print(b.utcoffset())
print(b.tzname())
print(b.dst())
# Вывод:
2021-07-23 06:15:04.711995+00:00
2021-07-23 11:28:25.711995+05:13:21
5:13:21
UTC
0:00:00