Перейти к содержанию

412 уроков, 25 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 2 из 20 Начальный 15 мин 100 XP

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, просто с добавленным временем. На практике это приводит к тому, что код, который якобы отделяет даты от моментов, на самом деле не отделяет ничего.

isinstance.py — порядок проверок решает всё
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 идёт первой, и тогда каждый объект попадает в свою корзину.

isinstance_fixed.py — сначала 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 здесь спасает: она всплывает сразу, а не превращается в неверный результат. Обычно это означает, что данные пришли из двух разных источников: один отдаёт календарные даты, другой — моменты времени. Приводить их к общему классу надо на границе, где вы разбираете входные данные, а не в пяти местах по коду.

compare.py — разные классы не сравниваются
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.

narrow.py — свести к одному классу
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, который делает то же самое одной строкой и заодно проверяет, что на вход поданы объекты правильных классов. Второй способ мы предпочитаем почти всегда: он короче и не ошибается в порядке аргументов.

assemble.py — собрать момент из даты и времени
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)
Проверь себя
0 / 8

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 объект только с датой?

Карточки терминов
Запомнено: 0 / 8
Практика

Из момента собрания — 21 октября 2026 года, 12:30 — извлеки дату и время, выведи их по отдельности, а затем выведи день месяца из полученной даты.

practice.py
Вопросы и ответы по уроку

Чем 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-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.