date, time и datetime: три класса
День рождения без часов, будильник без календаря, лог-запись со всем сразу. Три класса модуля datetime — и правило, какой выбрать под задачу.
Редакция Питоники
datetime из первого урока хранит всё сразу — и календарь, и часы. Но не каждой задаче нужно всё: у дня рождения часов нет, у будильника нет календаря, а у записи в логе есть и то и другое. Держать «просто дату» в полноценном datetime — как хранить рост человека вместе с историей его стрижек: можно, но зачем. Поэтому в модуле datetime живут три класса под три разных задачи.
Три класса одного модуля
Знакомимся: date(2026, 10, 21) — только год, месяц и день; time(12, 30) — только часы, минуты и секунды, без всякого календаря; datetime — момент целиком, обе половины сразу. Печатаются они по-разному: date — ISO-датой, time — временем суток через двоеточия, datetime — склейкой обеих частей через пробел. Атрибуты делятся так же: у date — year, month, day; у time — hour, minute, second; datetime держит все шесть. И граница между классами настоящая: спросить у date, который час, не выйдет.
from datetime import date, datetime, time
print(date(2026, 10, 21))
print(time(12, 30))
print(datetime(2026, 10, 21, 12, 30))
2026-10-21 12:30:00 2026-10-21 12:30:00
Извлекаем части: date() и time()
from datetime import datetime
meeting = datetime(2026, 10, 21, 12, 30)
print(meeting.date())
print(meeting.time())
print(type(meeting.date()))
print(type(meeting.time()))
2026-10-21 12:30:00 <class 'datetime.date'> <class 'datetime.time'>
date() и time() не режут строку — они возвращают настоящие объекты соответствующих классов, со всеми полями и методами. Из даты встречи можно взять месяц (meeting.date().month), из времени — секунды (meeting.time().second), и всё это честные числа. Обратная сборка — из date и time сделать datetime — называется combine, и ей посвящён урок 11; сегодня важно само умение разбирать момент на части.
Какой класс выбрать
Правило простое: выбирай самый узкий класс, которого хватает задаче. День рождения — date: отмечается по календарю, а не по часам. Начало рабочего дня — time. А «заказ оформлен 21 октября в 12:30» — datetime, потому что без обеих частей событие не опишешь.
| Класс | Хранит | Подходит для |
|---|---|---|
| date | год, месяц, день | дни рождения, дедлайны без времени, даты в отчётах |
| time | часы, минуты, секунды | расписание звонков, график работы, время напоминания |
| datetime | дата и время вместе | логи, события, сроки платежей, всё, что привязано к моменту |
Одна минута: datetime — это подкласс date
Есть деталь, на которой спотыкаются даже опытные разработчики: datetime — не сосед date, а его подкласс. Проверка isinstance намекает на это сама собой, но в коде это означает совершенно конкретную ловушку. Если вы перебираете разнородные записи и спрашиваете isinstance(x, date), то моменты datetime тоже подойдут — isinstance вернёт True, потому что момент и правда date, просто с добавленным временем. На практике это приводит к тому, что код, который якобы отделяет даты от моментов, на самом деле не отделяет ничего.
from datetime import date, datetime
items = [date(2026, 10, 21), datetime(2026, 10, 21, 14, 30)]
for item in items:
if isinstance(item, date):
kind = 'дата'
else:
kind = 'момент'
print(kind, item)
дата 2026-10-21 дата 2026-10-21 14:30:00
Второй объект — момент с временем, а код назвал его датой. Лечится перестановкой: сначала спрашиваем про более узкий класс, потом про более широкий. Проверка на datetime идёт первой, и тогда каждый объект попадает в свою корзину.
from datetime import date, datetime
items = [date(2026, 10, 21), datetime(2026, 10, 21, 14, 30)]
for item in items:
if isinstance(item, datetime):
kind = 'момент'
elif isinstance(item, date):
kind = 'дата'
print(kind, item)
дата 2026-10-21 момент 2026-10-21 14:30:00
Смешивать классы в сравнениях нельзя
Второй подводный камень связан с первым. Сравнить date с datetime не получится — даже если дата и момент описывают один и тот же день: оператор честно откажется сравнивать объекты разных классов. Ошибка TypeError здесь спасает: она всплывает сразу, а не превращается в неверный результат. Обычно это означает, что данные пришли из двух разных источников: один отдаёт календарные даты, другой — моменты времени. Приводить их к общему классу надо на границе, где вы разбираете входные данные, а не в пяти местах по коду.
from datetime import date, datetime
d = date(2026, 10, 21)
m = datetime(2026, 10, 21, 14, 30)
try:
print(d < m)
except TypeError:
print('Ошибка: классы разные, сравнение невозможно')
print(date(2026, 10, 21) < date(2026, 10, 22))
Ошибка: классы разные, сравнение невозможно True
Текст ошибки Python менялся от версии к версии: в 3.12 сообщение выглядело как «can't compare datetime.datetime to datetime.date», в 3.13 — как «'<' not supported between instances of 'datetime.date' and 'datetime.datetime'». Поэтому в рабочем коде ориентируйтесь на сам тип исключения, TypeError, а не на формулировку: перехватывайте класс ошибки, а не сравнивайте строки. В примере выше мы так и сделали — поймали TypeError и напечатали свою строку, поэтому вывод одинаков в любой версии.
Приём, который мы используем в проектах: привести всё к одному классу на входе. Если в системе даты и моменты лежат рядом, приводите моменты к датам через .date() — и сравнивайте даты. Обратный путь, от даты к моменту, требует указания времени и делается вручную или через combine, о котором пойдёт речь в уроке 11.
from datetime import date, datetime
d = date(2026, 10, 21)
m = datetime(2026, 10, 21, 14, 30)
print(m.date() < date(2026, 10, 22))
print(d == m.date())
True True
Второй момент здесь — про выбор класса на входе. Когда форма или база отдают дату, но с ней потом сравнивают момент, разумнее привести всё к date на границе, чем городить проверки в каждом сравнении. Мы в рабочих проектах держим правило: тип определяется при разборе данных, а дальше по коду ходит уже один класс. Когда данных меньше тысячи строк, это не вопрос производительности, а вопрос читаемости — проверок становится меньше, и каждый разработчик в команде понимает, что сравнивает.
Обратное преобразование: из двух полей — один момент
Раз date и time не превращаются друг в друга, момент приходится собирать из кусков. Способов два. Первый — ручной: взять год, месяц и день у даты, часы и минуты у времени и передать их конструктору. Работает, но требует внимания: забытый аргумент сдвигает момент на полночь. Второй — datetime.combine, который делает то же самое одной строкой и заодно проверяет, что на вход поданы объекты правильных классов. Второй способ мы предпочитаем почти всегда: он короче и не ошибается в порядке аргументов.
from datetime import date, datetime, time
d = date(2026, 10, 21)
t = time(14, 30)
manual = datetime(d.year, d.month, d.day, t.hour, t.minute)
print(manual)
print(datetime.combine(d, t))
2026-10-21 14:30:00 2026-10-21 14:30:00
date — календарь без часов, time — часы без календаря, datetime — момент целиком: самый узкий класс, которого хватает задаче, и есть правильный.
Сначала предскажи ответ в голове — это главный навык программиста.
from datetime import datetime
moment = datetime(2026, 10, 21, 12, 30)
print(moment.date().month)
from datetime import date, time
print(date(2026, 10, 21), time(23, 59, 59))
from datetime import datetime
meeting = datetime(2026, 10, 21, 12, 30)
d = meeting.date()
print(d.year, d.day)
from datetime import date, datetime
items = [date(2026, 10, 21), datetime(2026, 10, 21, 14, 30)]
for item in items:
if isinstance(item, date):
kind = 'дата'
else:
kind = 'момент'
print(kind, item)
1. Что выведет print(time(12, 30))?
2. Какие поля есть у объекта date(2026, 10, 21)?
3. Что вернёт meeting.date() для datetime(2026, 10, 21, 12, 30)?
4. Для какой задачи правильнее выбрать time, а не datetime?
5. Что упадёт с ошибкой AttributeError?
6. Что вернёт isinstance(datetime(2026, 10, 21, 14, 30), date)?
7. Что произойдёт при попытке сравнить date и datetime?
8. Как получить из момента 2026-10-21 14:30 объект только с датой?
Из момента собрания — 21 октября 2026 года, 12:30 — извлеки дату и время, выведи их по отдельности, а затем выведи день месяца из полученной даты.
Чем date отличается от datetime в Python?
date хранит только календарную дату — год, месяц, день; datetime — дату плюс время суток. Если время не нужно (день рождения, дедлайн без часов), бери date: меньше полей — меньше шансов запутаться, и сравнения остаются честными.
Урок 1: первый datetimeКак извлечь дату из datetime?
Методом date(): moment.date() вернёт объект класса date с полями year, month, day. Симметрично moment.time() вернёт время суток. Оба метода возвращают настоящие объекты, а не строки — из них можно читать поля и передавать их дальше.
Какой класс выбрать: date, time или datetime?
Правило — самый узкий класс, которого хватает: подпись письма и дни рождения — date; расписание звонков и время напоминаний — time; лог события, срок платежа — datetime. Все три живут в одном модуле и конвертируются: date() и time() разбирают момент, combine собирает обратно.
Урок 11: combine и replaceЧто произойдёт, если сравнить date и datetime?
Python выбросит TypeError: сравнение даты и момента не поддерживается. Ошибка здесь полезна — она всплывает сразу. Приводите значения к одному классу на входе: moment.date() даёт date, и тогда сравнение проходит.
Почему isinstance(moment, date) возвращает True?
Потому что datetime наследуется от date: момент — это дата плюс время, а не что-то параллельное. Отсюда порядок проверок в коде: isinstance спрашивают сначала про datetime и только потом про date, иначе моменты не отличить от дат.
Урок 7: сравнение датКак привести дату к моменту времени?
Самый чистый путь — datetime.combine(date(2026, 10, 21), time(14, 30)): он склеивает календарный день и время суток в полноценный момент. Вручную это выглядит как datetime(d.year, d.month, d.day, t.hour, t.minute) — работает, но длиннее.
Урок 11: combine и replaceУмеет ли datetime разбирать дату из строки, как strptime?
Да, у каждого класса есть свой fromisoformat: date.fromisoformat('2026-10-21') вернёт дату, time.fromisoformat('14:30') — время суток. Метод понимает только ISO-формат, зато понимает его целиком: без шаблона и без ошибок на перепутанных разделителях.
Урок 10: isoformatПонравился урок? Сошлитесь на него
«date() и time() не режут строку — они возвращают настоящие объекты соответствующих классов, со всеми полями и методами.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Datetime · Урок 1
datetime в Python: первый момент времени
Дата как строка не умеет ничего: ни сравниться, ни посчитаться. Создаём первый объект datetime и разбираем его на поля — от года до секунды.
Datetime · Урок 3
now и today: текущий момент
Фиксированные даты хороши для примеров, а для логов и дедлайнов нужен настоящий сейчас. Учимся получать текущий момент — и понимать, почему вывод перестаёт быть предсказуемым.
Datetime · Урок 7
Сравнение и сортировка дат
Даты сравниваются как числа — и потому сортируются, выбираются min и max и становятся ключами словаря. Разбираем операторы и честную сортировку без строковых сюрпризов.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
ООП · Урок 1
Классы в Python: первый объект
Класс — чертёж, объект — экземпляр по этому чертежу. Создаём первый класс, вызываем методы и убеждаемся: в Python объектом является всё, включая функции.
классы pythonpython классы
ООП · Урок 10
Абстрактные классы: ABC и @abstractmethod
Абстрактный класс объявляет контракт: какие методы обязан иметь каждый потомок, — и запрещает создавать объекты, пока контракт не выполнен. Разбираем ABC, @abstractmethod и шаблонный метод.
абстрактный класс pythonнельзя создать абстрактный класс
Datetime · Урок 8
Коды форматирования strftime: полная шпаргалка
strftime превращает datetime в строку по шаблону из кодов: %Y — год, %m — месяц, %H — часы. Собираем полную шпаргалку с примерами вывода на одной фиксированной дате.
коды форматирования даты pythonформат даты python