Перейти к основному содержимому

Даты и время в Python

Разработчику

См. также: Работа с типами · Анализ данных — pandas · Работа с файлами и API


Модуль datetime

Стандартный пакет datetime (не путать с именем типа) покрывает календарные даты, время суток, длительности и часовые пояса. Для логов, отчётов, API и аналитики это основной инструмент; в pandas временные ряды опираются на те же идеи — см. практикум по pandas.

Основные типы:

ТипНазначение
dateКалендарный день (год, месяц, день)
timeВремя суток без даты
datetimeДата + время
timedeltaРазница двух моментов (дни, секунды, микросекунды)
timezoneСмещение от UTC (фиксированное)

Создание и "сейчас"

from datetime import date, datetime, time, timedelta

today = date.today()
now = datetime.now() # локальное время ОС, наивное

d = date(2026, 5, 25)
dt = datetime(2026, 5, 25, 14, 30, 0)
t = time(9, 0, 0)

Разбор примера:

  • Импортируются четыре основных типа из модуля datetime.
  • date.today() возвращает только календарную дату без времени.
  • datetime.now() возвращает текущие дату и время в локальной зоне ОС.
  • date(...), datetime(...) и time(...) создают значения с явно заданными компонентами.

datetime.now() и date.today() зависят от часового пояса системы. Для серверного кода предпочтительнее явная зона или UTC.


Наивные и осознанные (aware) объекты

Наивный datetime не содержит информации о поясе — только "стенные часы". Осознанный привязан к tzinfo (часто через zoneinfo в Python 3.9+).

from datetime import datetime, timezone
from zoneinfo import ZoneInfo

utc = datetime.now(timezone.utc)
moscow = datetime.now(ZoneInfo("Europe/Moscow"))

# перевод осознанного момента
moscow_from_utc = utc.astimezone(ZoneInfo("Europe/Moscow"))

Разбор примера:

  • timezone.utc задаёт объект часового пояса UTC.
  • ZoneInfo("Europe/Moscow") подключает региональную зону из базы IANA.
  • datetime.now(...) в обоих случаях создаёт aware-объекты с tzinfo.
  • astimezone(...) переводит один и тот же момент времени в другую зону.

Правило для backend и БД:

  • хранить и передавать UTC (или Unix timestamp);
  • переводить в локаль пользователя на границе (UI, отчёт);
  • не сравнивать наивный и осознанный datetime — будет TypeError.
# Ошибка — смешение наивного и aware
# naive < aware # TypeError

timedelta — арифметика длительностей

from datetime import datetime, timedelta

start = datetime(2026, 1, 1, 12, 0)
end = start + timedelta(days=7, hours=3)
delta = end - start
print(delta.days, delta.seconds) # целые дни и остаток секунд

Разбор примера:

  • timedelta(days=7, hours=3) описывает длительность 7 дней и 3 часов.
  • Операция start + timedelta(...) сдвигает момент времени вперёд.
  • Разность end - start возвращает объект timedelta.
  • Поля days и seconds дают представление длительности в удобной форме.

timedelta не привязан к календарю: "+1 месяц" делают через dateutil.relativedelta (сторонняя библиотека) или логику pandas.


Форматирование и разбор строк

from datetime import datetime

dt = datetime(2026, 5, 25, 9, 5, 0)
text = dt.strftime("%Y-%m-%d %H:%M:%S") # "2026-05-25 09:05:00"
parsed = datetime.strptime("25.05.2026", "%d.%m.%Y")

Разбор примера:

  • strftime(...) форматирует объект datetime в строку по шаблону.
  • %Y, %m, %d отвечают за год, месяц и день; %H, %M, %S — за время.
  • strptime(...) выполняет обратную операцию: парсит строку по указанному формату.
  • Формат входной строки и шаблон должны совпадать буквально, иначе будет ValueError.
КодЗначение
%YГод четырьмя цифрами
%mМесяц 01–12
%dДень
%HЧас 00–23
%MМинуты
%SСекунды

Месяц, день и время с ведущим нулём. Для отдельных компонентов даты и времени в виде двухзначной строки в Python 3.x используют два стандартных подхода. Оба возвращают str.

Способ 1 — strftime() (специализирован для datetime):

from datetime import datetime

dt = datetime(2026, 1, 5, 9, 7)

month = dt.strftime("%m") # "01"
day = dt.strftime("%d") # "05"
clock = dt.strftime("%H:%M:%S") # "09:07:00"

Способ 2 — f-строки (прямой доступ к атрибутам):

month = f"{dt.month:02d}" # "01"
day = f"{dt.day:02d}" # "05"
clock = f"{dt.hour:02d}:{dt.minute:02d}:{dt.second:02d}" # "09:07:00"

# Аналог через format():
# month = "{:02d}".format(dt.month)

Составной вывод текущей даты и времени:

now = datetime.now()
print(f"{now.day:02d}.{now.month:02d}.{now.year}") # "05.01.2026"
print(f"{now.day:02d}.{now.month:02d}.{now.year} {now.hour:02d}:{now.minute:02d}") # "05.01.2026 09:07"
КонструкцияЧто возвращаетТипПримечание
dt.strftime("%m")Месяц 0112strСтандарт POSIX/Python
dt.strftime("%d")День 0131strСтандарт POSIX/Python
dt.strftime("%H:%M:%S")Время 00:00:0023:59:59str24-часовой формат
f"{dt.month:02d}"Месяц 1120112strФорматирование целых чисел
f"{dt.day:02d}"День 1310131strФорматирование целых чисел
f"{dt.hour:02d}" и т.д.Час, минуты, секунды с нулёмstrАналог %H, %M, %S

Ведущий ноль сохраняется только в строковом представлении — при int("05") он исчезает, потому что целочисленный тип не хранит форматирование. Если нужен готовый составной формат (05.01.2026 или 05.01.2026 09:07), удобнее один вызов strftime: dt.strftime("%d.%m.%Y") или dt.strftime("%d.%m.%Y %H:%M"). Спецификаторы strftime регистрозависимы — %m это месяц, %M минуты; %d это день, %D дата в формате мм/дд/гг.

Для ISO 8601 удобнее методы экземпляра:

iso = dt.isoformat()
back = datetime.fromisoformat("2026-05-25T09:05:00+03:00")

Разбор примера:

  • isoformat() сериализует дату/время в стандарт ISO 8601.
  • fromisoformat(...) восстанавливает объект из ISO-строки.
  • В примере +03:00 добавляет информацию о смещении, поэтому результат aware.

В JSON API даты обычно сериализуют в строку UTC (...Z) или Unix timestamp — см. примеры в главе про файлы и API.


Часовые пояса и переход на летнее время

Фиксированный timezone(timedelta(hours=3)) не учитывает DST (летнее время). Для реальных регионов используйте zoneinfo.ZoneInfo (база IANA в стандартной библиотеке с 3.9) или pytz в legacy-коде.

Типичная ошибка: "добавить 24 часа" вместо "следующий календарный день" в поясе с переводом стрелок — сдвиг на час. Для бизнес-дат (дедлайн "до конца 25 мая") часто достаточно типа date без времени.


Связь с pandas и БД

  • pandas: pd.to_datetime(), индекс DatetimeIndex, dt.tz_localize / dt.tz_convert.
  • SQL: типы TIMESTAMP WITH TIME ZONE / DATETIME — драйвер возвращает datetime или строку; см. базы данных в Python.
  • Django: USE_TZ = True, модели DateTimeField хранят UTC в БД.

Практические рекомендации

  1. В логах — UTC + ISO формат.
  2. В тестах — фиксированные datetime, не now(), чтобы тесты были воспроизводимы.
  3. Сравнение "событие раньше дедлайна" — приводить обе стороны к одной зоне или к UTC.
  4. Для только даты рождения / даты документа — тип date, без времени и пояса.

Связанные материалы