Сравнение и сортировка дат
Даты сравниваются как числа — и потому сортируются, выбираются min и max и становятся ключами словаря. Разбираем операторы и честную сортировку без строковых сюрпризов.
Редакция Питоники
В уроке 1 мы поймали строки на лжи: '9.10.2026' > '10.10.2026' вернуло True, потому что строки сравниваются посимвольно. Для дат это была бы катастрофа: сентябрь оказался бы «позже» октября. Объекты date и datetime сравниваются честно — операторами, как числа. Именно поэтому даты можно сортировать, выбирать из них минимум и максимум и строить на них проверки «просрочено или нет».
Операторы сравнения
Все шесть операторов работают: <, >, <=, >=, ==, !=. Сравнивать можно только объекты одного класса: date с date, datetime с datetime. Равенство тоже по значению — два разных объекта с одинаковыми полями равны.
from datetime import date
deadline = date(2026, 11, 1)
sent = date(2026, 10, 21)
print(deadline < sent)
print(sent == date(2026, 10, 21))
print(sent <= deadline)
False True True
Сравнение идёт по полям: сначала годы, потом месяцы, потом дни — ровно как сравнивают числа, по разрядам. Поэтому даты разных лет и месяцев сравниваются за один оператор без ручных проверок. Один нюанс: спутать классы нельзя — datetime < date упадёт с TypeError: сравнение момента и даты не поддерживается, потому что это разные классы. Лечится приведением к общему классу: метод .date() из урока 2 срезает время, и сравнение проходит.
min, max и sorted
from datetime import date
dates = [
date(2026, 11, 1),
date(2026, 10, 21),
date(2026, 12, 5),
]
print(min(dates))
print(max(dates))
print(sorted(dates))
2026-10-21 2026-12-05 [datetime.date(2026, 10, 21), datetime.date(2026, 11, 1), datetime.date(2026, 12, 5)]
min и max возвращают самую раннюю и самую позднюю дату, sorted — новый список по возрастанию (параметр reverse=True перевернёт). В печать списка заглянул repr: datetime.date(...) — то самое отладочное лицо даты из первого урока. Сортировка ничего не стоит программисту: не нужно писать функцию сравнения или разбирать строки — объекты уже сравнимы. Со строками дат такой номер не прошёл бы: список из «9.10.2026» и «10.10.2026» отсортировался бы по алфавиту, и октябрь встал бы раньше сентября.
Даты как ключи словаря
from datetime import date
events = {
date(2026, 10, 21): 'деплой',
date(2026, 11, 1): 'релиз',
date(2026, 10, 30): 'аудит',
}
print(events[date(2026, 10, 30)])
for day in sorted(events):
print(day, events[day])
аудит 2026-10-21 деплой 2026-10-30 аудит 2026-11-01 релиз
Ключом словаря может быть только неизменяемый и хешируемый объект — дата подходит идеально: events[date(2026, 10, 30)] достаёт событие по дню без перебора. Печать ключей идёт ISO-строкой, и в таком словаре удобно хранить всё, что привязано к календарю: события, курсы валют, списки дел. Дальше по курсу: урок 10 — isoformat, строковый формат, который сортируется как дата; урок 16 — возраст и разница в днях, где сравнение и timedelta работают в паре.
Сортировка записей, у которых дата внутри
Наивный sorted на списке словарей не сработает: словари между собой не сравниваются, Python честно откажется. Но почти всегда сортировать нужно не даты, а записи, у которых дата лежит внутри — заказы, счета, тикеты. Решение — параметр key: функция, которая вызывается для каждого элемента, и по её результату идёт сортировка. Одна строка с lambda превращает список словарей в хронологический список.
from datetime import date
events = [
{'name': 'релиз', 'day': date(2026, 11, 1)},
{'name': 'деплой', 'day': date(2026, 10, 21)},
{'name': 'аудит', 'day': date(2026, 10, 28)},
]
for event in sorted(events, key=lambda item: item['day']):
print(event['day'], event['name'])
2026-10-21 деплой 2026-10-28 аудит 2026-11-01 релиз
Здесь стоит остановиться и подумать, а не просто скопировать. Параметр key говорит: «сравнивай элементы по тому, что вернёт эта функция». Именно поэтому сортировка записей работает так же надёжно, как сортировка дат, — сравниваются всё те же объекты date, а не строки и не словари. Побочная выгода: ключ можно усложнить. Отсортировать по дате, а при совпадении — по имени, — это key=lambda item: (item['day'], item['name']), и никаких отдельных функций сравнения писать не нужно.
Ближайшая дата к заданной
Отдельная задача, которая на проектной работе возникает чаще, чем кажется: есть список дат и есть опорная дата, надо найти ближайшую к ней. В общем виде задача выглядит так: взять расстояние от каждой даты до цели и выбрать минимальное. Расстояние считается через разницу в днях, а искать минимум умеет min с тем же параметром key.
from datetime import date
target = date(2026, 10, 25)
days = [date(2026, 10, 21), date(2026, 11, 1), date(2026, 10, 28)]
nearest = min(days, key=lambda d: abs((d - target).days))
print(nearest)
print(abs((nearest - target).days))
2026-10-28 3
Модуль abs здесь не лишний: без него min нашёл бы самую раннюю дату вместо ближайшей, потому что отрицательные расстояния меньше положительных. А вот max с тем же ключом дал бы самую далёкую — иногда это тоже нужно, но называть это «ближайшей» нельзя. Если в списке есть и прошлое, и будущее, а вам нужна ближайшая именно в будущем, условие меняют: берут только даты позже цели.
from datetime import date
items = [date(2026, 10, 21), '2026-10-22']
try:
print(sorted(items))
except TypeError:
print('смешанные типы не сравниваются')
смешанные типы не сравниваются
Равенство — это не идентичность
Сравнение дат стоит различать с проверкой идентичности. Два объекта date с одинаковыми полями равны, но это разные объекты в памяти. Оператор is для дат бесполезен и почти всегда даёт False: он спрашивает, не один ли это объект, а не про поля. В словаре это не мешает, потому что там ключи сравниваются по значению, — а вот код вида if event.date() is today будет вести себя непредсказуемо.
from datetime import date
a = date(2026, 10, 21)
b = date(2026, 10, 21)
print(a == b)
print(a is b)
True False
Даты сравниваются по значению полей, а не по порядку появления в памяти: поэтому их можно класть в словари, сортировать списком и сравнивать между собой без единой вспомогательной функции.
Сравнение дат, когда типы разные: ловушка TypeError
Сравнивать даты в Python приятно, пока не сравниваются разные типы. date и datetime — близкие родственники: datetime действительно подкласс date, и на первый взгляд сравнение должно работать. Но Python всё равно отказывает, потому что сравнение момента с датой бессмысленно: у datetime есть часы, минуты и секунды, а у date нет, и «раньше» тут не определено. Проверка date < datetime падает с TypeError — и, что важно для отладки, текст этой ошибки в Python 3.12 и 3.13 разный: в 3.12 это «can't compare datetime.datetime to datetime.date», в 3.13 — «'<' not supported between instances of 'datetime.date' and 'datetime.datetime'». Один и тот же код, одна и та же ошибка, два разных текста.
Из этого следует практическое правило: приводите обе стороны к одному типу до сравнения, а не ловите TypeError. Если работаете с датами из JSON или из базы — приведите их к date на границе входа, и дальше сравнивайте уже однородные значения. Намеренно ловить исключение здесь — плохая идея: сообщение об ошибке зависит от версии Python, и код, который на неё завязан, сломается при обновлении.
from datetime import date, datetime
day = date(2026, 10, 21)
moment = datetime(2026, 10, 21, 14, 30)
print(day < moment.date())
print(day == moment.date())
False True
И не забывайте про порядок: в Python даты сравниваются по календарю, то есть 2026-10-30 позже 2026-09-01. Для строк то же самое работает только при одинаковом формате во всех данных — и то, пока это ISO, где порядок цифр совпадает с хронологическим. Про то, почему такие строки удобно сортировать без разбора, — в уроке 10.
Сначала предскажи ответ в голове — это главный навык программиста.
from datetime import date
dates = [
date(2026, 11, 1),
date(2026, 10, 21),
date(2026, 12, 5),
]
print(min(dates), max(dates))
from datetime import date
dates = [date(2026, 12, 5), date(2026, 10, 21)]
print(sorted(dates))
from datetime import date
events = {
date(2026, 11, 1): 'релиз',
date(2026, 10, 21): 'деплой',
}
print(events[max(events)])
from datetime import date
events = [
{'name': 'релиз', 'day': date(2026, 11, 1)},
{'name': 'деплой', 'day': date(2026, 10, 21)},
]
for event in sorted(events, key=lambda item: item['day']):
print(event['name'], event['day'])
1. Что вернёт date(2026, 10, 21) < date(2026, 11, 1)?
2. Как сравниваются даты по полям?
3. Что произойдёт при сравнении datetime с date?
4. Что вернёт sorted(dates) для списка дат?
5. Почему даты можно использовать как ключи словаря?
6. Почему список строк '9.10.2026' и '10.10.2026' сортируется неверно?
7. Как отсортировать список словарей по дате, лежащей внутри записи?
8. Что вернёт print(a == b) и print(a is b) для двух date(2026, 10, 21)?
9. Как найти дату, ближайшую к заданной, среди списка?
Дан список дат — 14 ноября, 21 октября, 5 декабря и 1 сентября 2026 года — все вперемешку. Выведи самую раннюю, самую позднюю и весь список по возрастанию.
Как сравнить две даты в Python?
Обычными операторами: date(2026, 10, 21) < date(2026, 11, 1) вернёт True. Сравнение идёт по значению — годы, затем месяцы, затем дни. Единственное правило: классы должны совпадать, datetime с date напрямую не сравнивается.
Урок 7: сравнение датКак отсортировать список дат?
Функцией sorted: sorted(dates) вернёт новый список по возрастанию, параметр reverse=True — по убыванию. Отдельная функция сравнения не нужна: объекты date и datetime уже сравнимы. Именно поэтому даты стоит держать как объекты, а не как строки.
Можно ли использовать дату как ключ словаря?
Да: date и datetime неизменяемы и хешируемы, поэтому словарь вида {date(2026, 10, 21): 'деплой'} работает — значение достаётся по дате без перебора. Обход в хронологическом порядке даёт for day in sorted(events).
Как найти ближайшую дату из списка?
min(dates) — самая ранняя, max(dates) — самая поздняя. Для «ближайшей к сегодня» сравнивают разницы через timedelta или берут минимум по ключу min(dates, key=...), но базовые min и max уже закрывают поиск крайних дат.
Урок 6: timedeltaКак отсортировать список заказов по дате, если дата лежит внутри записи?
Через параметр key: sorted(orders, key=lambda item: item['date']). Функция вызывается для каждой записи, и сортировка идёт по её результату — то есть по объекту date, а не по строке и не по самому словарю.
Как найти ближайшую к сегодняшнему дню дату из списка?
min(days, key=lambda d: abs((d - target).days)) — считаем расстояние в днях и берём минимум. Функция abs обязательна: без неё отрицательные расстояния до прошлых дат всегда «меньше», и min вернёт самую раннюю дату вместо ближайшей.
Урок 6: timedeltaМожно ли сравнить date с datetime, если дата и момент описывают один день?
Нет, получится TypeError: '<' not supported between instances of 'datetime.date' and 'datetime.datetime'. Приводите к общему классу: moment.date() даёт date, и тогда сравнение проходит. Ошибка здесь полезна — она всплывает сразу, а не превращается в неверный результат.
Урок 2: date, time и datetimeПонравился урок? Сошлитесь на него
«Сравнение идёт по полям: сначала годы, потом месяцы, потом дни — ровно как сравнивают числа, по разрядам.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Datetime · Урок 1
datetime в Python: первый момент времени
Дата как строка не умеет ничего: ни сравниться, ни посчитаться. Создаём первый объект datetime и разбираем его на поля — от года до секунды.
Datetime · Урок 6
timedelta: разница между моментами
«Срок подписки истекает через 7 дней», «событие было 3 часа назад» — за этим стоит timedelta. Вычитаем моменты, читаем дни и секунды, прибавляем разницу к датам.
Datetime · Урок 10
isoformat и fromisoformat: ISO-даты
Один вызов — и datetime превращается в строку 2026-10-21T14:30:45. ISO-формат сортируется как текст, а fromisoformat читает его обратно без единого кода %.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
json · Урок 16
Сортировка и топ-N: sorted по ключу
Список из API приходит в том порядке, в каком отдал сервер: sorted с key наводит порядок, reverse разворачивает, срез берёт топ-3.
python сортировка списка словарейsorted key lambda python
Словари · Урок 2
Создание словаря: фигурные скобки и dict()
Три способа создать словарь: литерал в фигурных скобках, dict() из списка пар и пустой словарь под наполнение. Плюс разбор, какие ключи годятся и почему fromkeys с пустым списком — ловушка.
создание словаря pythonсловарь из списка пар
Datetime · Урок 2
date, time и datetime: три класса
День рождения без часов, будильник без календаря, лог-запись со всем сразу. Три класса модуля datetime — и правило, какой выбрать под задачу.
date time datetime pythonpython date