> Как посчитать возраст в годах между текущей датой и датой рождения в Python (Python)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Ozon

Стек: Python

> Пример ответа

Короткий ответ

Для расчёта возраста в годах нужно учитывать, прошёл ли день рождения в текущем году. Простое вычитание date.today().year - birth_date.year даст неверный результат, если день рождения ещё не наступил. Корректный подход - вычислить разницу лет и скорректировать её на основе сравнения месяца и дня. Используйте date из стандартного модуля datetime, без сторонних библиотек.

Подробное объяснение

Основная сложность - календарная логика, а не арифметика. Разница в годах между двумя датами не равна целому числу дней, делённому на 365.25, потому что:

  • високосные годы добавляют 29 февраля;
  • день рождения может приходиться на 29 февраля, и в невисокосный год его формально нет.

Корректный алгоритм:

  1. Вычислить years = today.year - birth.year.
  2. Если (today.month, today.day) < (birth.month, birth.day), уменьшить years на 1.

Это работает для всех дат, включая 29 февраля: в невисокосный год (2, 28) < (2, 29) - возраст ещё не наступил, а в високосный - наступил.

Альтернативный подход - использовать dateutil.relativedelta, но для простой задачи это избыточно. Стандартная библиотека достаточна.

На практике

В реальном backend-коде возраст обычно нужен для валидации (например, 18+), отображения или расчёта страховых премий. Важно:

  • всегда использовать локальную дату, а не UTC, если речь о пользователе;
  • не доверять вводу даты рождения - валидировать формат и диапазон;
  • если возраст нужен для юридических целей, уточнить, как трактовать 29 февраля (обычно - 1 марта в невисокосный год, но это бизнес-правило).

Функция должна быть чистой: принимать birth_date и today (с дефолтом date.today()), чтобы её можно было тестировать с фиксированными датами.

Пример кода

PYTHON
from datetime import date
def calculate_age(birth_date: date, today: date | None = None) -> int:
"""Возвращает полное количество лет на дату today."""
if today is None:
today = date.today()
if today < birth_date:
raise ValueError("today must be after birth_date")
years = today.year - birth_date.year
# Если день рождения ещё не наступил в этом году
if (today.month, today.day) < (birth_date.month, birth_date.day):
years -= 1
return years
# Примеры
print(calculate_age(date(2000, 2, 29), date(2024, 2, 28))) # 23
print(calculate_age(date(2000, 2, 29), date(2024, 2, 29))) # 24
print(calculate_age(date(1990, 5, 15), date(2024, 5, 14))) # 33
print(calculate_age(date(1990, 5, 15), date(2024, 5, 15))) # 34

Как отвечать на собеседовании

Начните с короткого ответа, затем покажите код. Подчеркните, что учитываете граничные случаи: 29 февраля, день рождения сегодня, дата рождения в будущем. Объясните, почему не используете timedelta - он не даёт календарных лет. Если спросят про dateutil, скажите, что это допустимо, но для одной функции не нужно тащить зависимость. Упомяните, что функция тестируема благодаря параметру today.

Что проверяет интервьюер

  • Понимание календарной логики, а не механического вычитания.
  • Умение обрабатывать edge cases: високосный год, 29 февраля, границы месяца.
  • Чистоту функции: отсутствие side effects, явные параметры.
  • Знание стандартной библиотеки datetime.
  • Способность объяснить trade-off между простотой и точностью.

Типичные ошибки

  • Вычитание today.year - birth.year без коррекции - даёт завышенный возраст до дня рождения.
  • Использование timedelta(days=365.25) - накапливает ошибку и некорректно для 29 февраля.
  • Сравнение только месяца без дня - ломается в первый день месяца.
  • Игнорирование случая, когда birth_date в будущем - приводит к отрицательному возрасту.
  • Жёсткая привязка к date.today() внутри функции - усложняет тестирование.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью