Avatar ·

Как вычислить возраст человека по дате рождения (DateTime) в C#?

Всем привет! Я новичок в C# и пишу небольшое приложение для учёта клиентов. Мне нужно автоматически вычислять возраст человека на основе его даты рождения, которая хранится в виде `DateTime`. Проблема в том, что просто вычесть текущую дату из даты рождения и поделить на 365 — не работает корректно. Високосные годы, разное количество дней в месяцах — всё это даёт погрешность. Я пробовал такой код: ```csharp DateTime birthDate = new DateTime(2000, 2, 29); // 29 февраля DateTime today = DateTime.Today; int age = (today - birthDate).Days / 365; Console.WriteLine(age); // Иногда выводит 23, хотя должно быть 24 ``` Но для людей, родившихся 29 февраля, или для тех, у кого день рождения ещё не наступил в текущем году, результат получается неверным. Как правильно и надёжно вычислить возраст в годах с учётом всех этих нюансов? Нужно решение, которое будет работать для любых дат, включая 29 февраля. Заранее спасибо за помощь! <<>>

Правильный расчёт возраста с учётом високосных годов и граничных случаев

Проблема с простым делением на 365 действительно даёт ошибки из-за високосных годов. Корректный подход — вычислять возраст на уровне целых лет, проверяя, был ли уже день рождения в текущем году. Вот надёжное решение:

public static int CalculateAge(DateTime birthDate, DateTime referenceDate)
{
    // Вычисляем разницу в годах
    int age = referenceDate.Year - birthDate.Year;

    // Если день рождения в текущем году ещё не наступил, вычитаем 1 год
    if (referenceDate.Month < birthDate.Month || 
       (referenceDate.Month == birthDate.Month && referenceDate.Day < birthDate.Day))
    {
        age--;
    }

    return age;
}

// Использование:
DateTime birthday = new DateTime(2000, 2, 29);
DateTime today = DateTime.Today;
int age = CalculateAge(birthday, today);
Console.WriteLine($"Возраст: {age}");

Почему это работает?

  • Базовая разница годов: Сначала мы берём разницу между годами — это максимальный возможный возраст.
  • Коррекция на день рождения: Если текущий месяц меньше месяца рождения, или месяц равен, но день ещё не наступил — значит, день рождения в этом году ещё не был, и возраст нужно уменьшить на 1.
  • Работа с 29 февраля: Если человек родился 29 февраля 2000 года, а сегодня 28 февраля 2024 года, то условие referenceDate.Day < birthDate.Day сработает (28 < 29), и возраст будет 23, а не 24. Если же сегодня 1 марта — условие не сработает, и возраст станет 24. Это корректно, так как в невисокосные годы день рождения формально наступает 1 марта (или считается, что 28 февраля, но логика остаётся верной).

Упрощённый вариант (без отдельного метода)

Если вам не нужна отдельная функция, можно встроить расчёт напрямую:

DateTime birthDate = new DateTime(1990, 5, 15);
DateTime today = DateTime.Today;

int age = today.Year - birthDate.Year;
if (today.Month < birthDate.Month || 
    (today.Month == birthDate.Month && today.Day < birthDate.Day))
{
    age--;
}

Console.WriteLine($"Возраст: {age}");

Обработка краевых случаев

Этот подход корректно обрабатывает:

  • Людей, родившихся 29 февраля
  • Ситуации, когда день рождения ещё не наступил в текущем году
  • Любые високосные годы
  • Даты рождения в прошлом и будущем (если дата рождения в будущем, возраст будет отрицательным — это нормально для валидации)

Важно: Для вычисления возраста на текущую дату используйте DateTime.Today, а не DateTime.Now, чтобы избежать влияния времени суток. Если нужно вычислить возраст на произвольную дату — передавайте её вторым параметром.

<<>>

Альтернативный подход с использованием DateTime.AddYears

Можно использовать встроенный метод DateTime.AddYears для более лаконичного решения:

public static int CalculateAge(DateTime birthDate, DateTime referenceDate)
{
    // Вычисляем возраст, прибавляя годы к дате рождения
    int age = referenceDate.Year - birthDate.Year;
    
    // Если после прибавления лет дата оказывается больше referenceDate, значит день рождения ещё не наступил
    if (birthDate.AddYears(age) > referenceDate)
    {
        age--;
    }
    
    return age;
}

Этот метод использует тот факт, что DateTime.AddYears корректно обрабатывает 29 февраля: если прибавить 1 год к 29 февраля 2000 года, то получится 28 февраля 2001 года (так как 2001 — невисокосный). Таким образом, сравнение будет точным. Код получается короче, но менее очевиден для новичков. Выбирайте тот вариант, который лучше понимаете.

Дополнительный совет: Для отображения возраста в годах, месяцах и днях можно использовать библиотеку NodaTime, но для простого возраста в годах приведённых решений более чем достаточно.