Работа с датой и временем в Python
Допустим, у нас лог-файл со строками вида 2026-05-20 14:30:42 ERROR ..., и нужно посчитать, сколько ошибок произошло за последние сутки. Для этого нужно: разобрать строку с датой в объект, посчитать разницу с «сейчас», и (если показывать пользователю) вернуть в его часовом поясе и привычном формате.
Эти три операции — парсинг строки, арифметика, форматирование — основа работы с датами в Python. Все они лежат в стандартном модуле datetime.
Три класса: datetime, date, time
В модуле datetime есть три основных класса, и важно понимать когда какой использовать:
- datetime: конкретный момент времени с точностью до микросекунд. Используется в 90% случаев.
- date: только дата, без времени. День рождения, дедлайн, дата заказа.
- time: только время суток, без даты. Время встречи в календаре.
Python 3.13from datetime import datetime, date, time # Момент времени now = datetime.now() print(now)2026-05-20 14:30:25.123456# Только дата birthday = date(1990, 5, 15) print(birthday)1990-05-15# Только время meeting = time(14, 30) print(meeting)14:30:00
У всех трёх классов есть отдельные атрибуты компонентов: .year, .month, .day, .hour, .minute, .second, .microsecond.
Python 3.13from datetime import datetime now = datetime(2026, 5, 20, 14, 30) print(now.year, now.month, now.day)2026 5 20print(now.weekday()) # 0 = понедельник, 6 = воскресенье2
Арифметика дат: timedelta
Прибавлять и вычитать даты можно напрямую: результат это timedelta (промежуток времени), либо новый datetime:
Python 3.13from datetime import datetime, timedelta now = datetime(2026, 5, 20, 14, 30) # Прибавить интервал week_later = now + timedelta(days=7) print(week_later)2026-05-27 14:30:00# Разница между моментами это timedelta deadline = datetime(2026, 6, 1) delta = deadline - now print(delta)11 days, 9:30:00print(delta.days, delta.total_seconds())11 985800.0
timedelta принимает days, hours, minutes, seconds, weeks, но не months и years (потому что они переменной длины: в феврале 28 или 29 дней, в году 365 или 366). Для прибавления месяцев есть библиотека dateutil (внешняя).
strftime и strptime: между объектом и строкой
В реальном коде даты постоянно проходят через строки — API, логи, базы данных. Запомнить какой метод что делает помогает мнемоника:
- strftime — format: объект → строка
- strptime — parse: строка → объект

Python 3.13from datetime import datetime # Объект → строка now = datetime(2026, 5, 20, 14, 30) print(now.strftime("%d.%m.%Y %H:%M"))20.05.2026 14:30print(now.strftime("%A, %d %B %Y"))Wednesday, 20 May 2026# Строка → объект parsed = datetime.strptime("20.05.2026 14:30", "%d.%m.%Y %H:%M") print(parsed)2026-05-20 14:30:00
Формат описывается строкой с директивами вида %Y, %m, %d:
ISO 8601: стандарт обмена датами
Если дату нужно передать между системами (API, JSON, базы данных), используется ISO 8601: 2026-05-20T14:30:00. У datetime есть готовые методы для этого формата, и они быстрее и надёжнее, чем strftime/strptime:
Python 3.13from datetime import datetime now = datetime(2026, 5, 20, 14, 30) # В ISO-строку iso_string = now.isoformat() print(iso_string)2026-05-20T14:30:00# Обратно parsed = datetime.fromisoformat("2026-05-20T14:30:00") print(parsed)2026-05-20 14:30:00
Правило: внутри программы держите даты как datetime-объекты, при выводе наружу (в JSON, в базу) — .isoformat(), при чтении снаружи — fromisoformat(). Свой формат с strftime нужен только когда мы показываем дату пользователю.
Часовые пояса: naive vs aware
datetime.now() без аргумента возвращает «наивный» (naive) datetime — у него нет информации о часовом поясе. Это распространённая грабля: программа работает «дома», а на сервере в другой стране внезапно показывает время на 7 часов раньше.
Правильно работать с aware datetime, у которого часовой пояс есть. С Python 3.9 для этого есть модуль zoneinfo, который умеет в реальные часовые пояса с учётом перехода на летнее время:
Python 3.13from datetime import datetime from zoneinfo import ZoneInfo # Aware datetime в UTC и Москве utc_now = datetime(2026, 5, 20, 14, 30, tzinfo=ZoneInfo("UTC")) moscow_now = utc_now.astimezone(ZoneInfo("Europe/Moscow")) print(utc_now)2026-05-20 14:30:00+00:00print(moscow_now)2026-05-20 17:30:00+03:00
Названия зон стандартизированы (IANA tz database): "Europe/Moscow", "America/New_York", "Asia/Tokyo". Когда вы храните datetime в базе данных, типичная практика: всегда хранить в UTC, конвертировать в локальную зону пользователя только при выводе.
Раньше для часовых поясов использовали внешнюю библиотеку pytz. С Python 3.9 встроенный zoneinfo это покрывает, и pytz больше не нужен.
Модуль time
Помимо datetime, есть низкоуровневый модуль time. Два его метода встречаются часто:
Python 3.13import time # Текущий момент как Unix timestamp (секунд с 1 января 1970) print(time.time())1779373825.123456# Пауза на N секунд print("Начало") time.sleep(0.1) print("Прошло 0.1 секунды")Начало Прошло 0.1 секунды
time.time() возвращает Unix timestamp — это формат, в котором часто хранят время в базах и логах: одно число, не зависит от часового пояса. Перевести в datetime можно через datetime.fromtimestamp(ts, tz=ZoneInfo("UTC")).
Проверка понимания
Какой класс из модуля datetime используется для представления промежутка времени?
В дальнейшем datetime будет встречаться часто: при работе с API (даты приходят строкой ISO 8601), с базами данных (хранение моментов событий), при логировании. Главное правило: внутри программы держите даты как объекты, превращайте в строки только на границе с внешним миром.
