Вычисление возраста в задачах JavaScript-обработки дат опирается на точное понимание календарной разницы между двумя моментами времени. В экосистеме работы с датами библиотека Day.js используется как компактная альтернатива Moment.js, предоставляя иммутабельную модель дат и цепочечный API, достаточный для большинства прикладных сценариев, включая расчёт возраста человека, аккаунта, события или любого временного интервала.
Возраст — это количество полных лет, прошедших между датой рождения и текущей датой. Ключевой момент заключается в том, что простое вычитание годов календаря не всегда даёт корректный результат. Необходимо учитывать, наступил ли уже день рождения в текущем году.
Формально задача сводится к вычислению:
В Day.js предусмотрен метод diff, позволяющий вычислять
разницу между датами в различных единицах измерения.
Простейшая реализация возраста:
import dayjs from 'dayjs';
const birthDate = dayjs('1995-06-10');
const now = dayjs();
const age = now.diff(birthDate, 'year');
Метод diff с параметром 'year' возвращает
количество полных лет между датами, автоматически отбрасывая неполные
периоды.
Однако такой способ не всегда учитывает пограничные случаи с точностью до дня, особенно если требуется строгая бизнес-логика.
Более точный способ заключается в проверке, наступил ли день рождения в текущем году. Логика строится на сравнении текущей даты с датой рождения, «перенесённой» в текущий год.
import dayjs from 'dayjs';
const birthDate = dayjs('1995-06-10');
const today = dayjs();
let age = today.year() - birthDate.year();
const birthdayThisYear = birthDate.year(today.year());
if (today.isBefore(birthdayThisYear, 'day')) {
age -= 1;
}
Здесь используется ключевой приём:
Такой подход обеспечивает календарную точность независимо от времени суток и часового пояса.
При вычислении возраста в серверных приложениях важно учитывать, что локальное время и UTC могут давать разные результаты в пограничные даты.
Day.js поддерживает плагины utc и timezone,
позволяющие фиксировать базовую систему отсчёта.
Пример с UTC:
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);
const birthDate = dayjs.utc('1995-06-10');
const now = dayjs.utc();
let age = now.year() - birthDate.year();
const birthdayThisYear = birthDate.year(now.year());
if (now.isBefore(birthdayThisYear, 'day')) {
age -= 1;
}
Использование UTC устраняет расхождения, связанные с локальными смещениями времени, особенно в распределённых системах.
Ещё один способ повышения читаемости логики — использование начала года как контрольной точки.
import dayjs from 'dayjs';
const birthDate = dayjs('1995-06-10');
const today = dayjs();
const yearsDiff = today.diff(birthDate, 'year');
const birthdayPassed = birthDate
.add(yearsDiff, 'year')
.isSameOrBefore(today, 'day');
const age = birthdayPassed ? yearsDiff : yearsDiff - 1;
Здесь вычисляется предварительная разница, после чего проверяется корректность попадания в текущий жизненный цикл года.
При вычислении возраста критичны следующие случаи:
В високосные годы возникают дополнительные сложности:
const birthDate = dayjs('2000-02-29');
const today = dayjs();
let age = today.diff(birthDate, 'year');
const leapYearBirthday = birthDate.year(today.year());
if (today.isBefore(leapYearBirthday, 'day')) {
age -= 1;
}
В не високосные годы Day.js автоматически интерпретирует 29 февраля как 1 марта при операциях с датами, что может потребовать дополнительной бизнес-логики.
Если дата рождения больше текущей даты:
const age = Math.max(0, dayjs().diff(dayjs('2030-01-01'), 'year'));
Без ограничений результат diff может быть отрицательным, что не всегда допустимо в прикладных системах.
В прикладных системах вычисление возраста часто выносится в отдельную функцию для обеспечения повторного использования:
import dayjs from 'dayjs';
export function calculateAge(dateString) {
const birthDate = dayjs(dateString);
const today = dayjs();
let age = today.diff(birthDate, 'year');
const birthdayThisYear = birthDate.year(today.year());
if (today.isBefore(birthdayThisYear, 'day')) {
age -= 1;
}
return age < 0 ? 0 : age;
}
Такая функция унифицирует поведение и снижает риск ошибок при повторном использовании логики в разных модулях.
В высоконагруженных системах использование Day.js для вычисления возраста остаётся эффективным благодаря:
Однако при массовых вычислениях (например, обработка миллионов записей) имеет смысл минимизировать создание временных объектов и заранее нормализовать даты рождения.
diff('year') без проверки дня
рожденияКорректная реализация всегда требует явного контроля календарного перехода, а не только арифметической разницы.