Класс datetime. Работа с датой и временем в Python

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

В случае необходимости экземпляр datetime разбирается на дату и время. Также можно выполнить обратное – собрать экземпляры date и time в один. В первом случае вызываются методы date() и time() экземпляра datetime. Во втором случае – метод combine(…) класса.

from datetime import datetime, date, time, timezone, timedelta
 
a = datetime(2023, 5, 19, 21, 49,
             tzinfo=timezone(timedelta(hours=3)))
print(a)  # 2023-05-19 21:49:00+03:00
print(a.date())  # 2023-05-19
print(a.time())  # 21:49:00
print(a.timetz())  # 21:49:00+03:00
 
d = date(2023, 5, 20)
t = time(10, 50, 34)
dt = datetime.combine(d, t)  # если бы в t был timezone, здесь он был бы также
dt_tz = datetime.combine(d, t, timezone(timedelta(hours=2)))
print(dt)  # 2023-05-20 10:50:34
print(dt_tz)  # 2023-05-20 10:50:34+02:00


Чтобы получить текущее время, используются классовые методы today и now. Первый возвращает местное время как наивное. Второй позволяет указать часовой пояс.

from datetime import datetime, timezone, timedelta
 
a = datetime.today()
print(a.strftime("%d %b %Y, %A, %H:%M"))
print(a.strftime("%d %b %Y, %A, %I:%M %p"))
 
b = datetime.now(timezone(timedelta(hours=3)))
print(b.strftime("%d %b %Y, %A, %H:%M %Z"))
 
c = datetime.now(timezone.utc)
print(c.strftime("%d %b %Y, %A, %H:%M %Z"))

Пример выполнения:

19 May 2023, Friday, 23:12
19 May 2023, Friday, 11:12 PM
19 May 2023, Friday, 23:12 UTC+03:00
19 May 2023, Friday, 20:12 UTC

В примере при создании третьего экземпляра datetime используется константа timezone.utc, которая содержит экземпляр timezone с нулевой таймдельтой.

Если вы хотите локальное время перевести в UTC или время какого-то другого часового пояса (выполнить корректировку часового пояса – time zone adjustments), то сделать это можно с помощью метода astimezone.

from datetime import datetime, timezone, timedelta
 
moscow = timezone(timedelta(hours=3), "Moscow")
new_york = timezone(timedelta(hours=-4), "New York")
 
a = datetime.now(moscow)
b = a.astimezone(new_york)
 
print(a.strftime("%H:%M:%S %Z"))
print(b.strftime("%H:%M:%S %Z"))
 
c = b.astimezone(timezone.utc)
print(c.strftime("\n%H:%M:%S %Z"))

Пример выполнения:

16:40:29 Moscow
09:40:29 New York

13:40:29 UTC

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

from datetime import datetime, timedelta, timezone
 
a = datetime(2023, 5, 26, 20, 30)
b = datetime.now(timezone(timedelta(hours=-4)))
print(b, end='\n\n')
 
a2 = a.astimezone()
b2 = b.astimezone()
 
print(a2, a2.tzname())
print(b2, b2.tzname())

Пример выполнения:

2023-05-21 10:01:17.873329-04:00

2023-05-26 20:30:00+03:00 MSK
2023-05-21 17:01:17.873329+03:00 MSK

В коде выше, применив astimezone без аргументов к наивному времени, мы получили это же самое время, но уже осведомленное. В данном случае – с указанием местного часового пояса.

Если надо не переводить время, а только изменить часовой пояс при сохранении тех же значений времени, используется метод replace. С его помощью также превращают осведомленное время в наивное.

from datetime import datetime, timedelta, timezone
 
a = datetime(2023, 5, 26, 20, 30,
             tzinfo=timezone(timedelta(hours=3)))
 
b = a.replace(tzinfo=timezone(timedelta(hours=-4)))
 
c = a.replace(tzinfo=None)  # наивное время
 
print(a.timetz())  # 20:30:00+03:00
print(b.timetz())  # 20:30:00-04:00
print(c.timetz())  # 20:30:00

Подобно date экземпляры datetime поддерживают следующие операции:

Однако, в связи с появлением свойства tzinfo, для сравнений действуют те же правила, что и для time.

Кроме того, вычисление разницы между двумя datetime возможно, когда обе даты с временем являются либо наивными, либо обе – осведомленными. Во втором случае при различных часовых поясах за кулисами выполняется приведение времени к UTC.

from datetime import datetime
 
a = datetime.fromisoformat("2023-05-21 19:05:23 +03:00")
b = datetime.fromisoformat("2023-05-22 00:05:23 +01:00")
 
ba = b - a
print(ba)  # 7:00:00
print(ba.__repr__())  # datetime.timedelta(seconds=25200)

В примере первое время соответствует 16-ти часам в зоне UTC, второе 23-м. Разница между моментами времени составляет 7 часов.

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

В то же время при сложении/вычитании datetime с timedelta у первого сохраняется его часовой пояс.

from datetime import datetime, timedelta
 
a = datetime.fromisoformat("2023-05-21 19:05:23 +03:00")
 
delta = timedelta(days=1, hours=5, minutes=30)
 
print(a + delta)  # 2023-05-23 00:35:23+03:00
print(a - delta)  # 2023-05-20 13:35:23+03:00

Атрибуты класса datetime (подчеркнуты не упомянутые в уроке):


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




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