К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как посчитать возраст в 1С: способы, код и проверка результата

Как посчитать возраст в 1С по дате рождения: готовые функции на встроенном языке, расчёт полных лет, учёт месяца и дня, типовые механизмы ЗУП и частые ошибки.

Задача вычисления возраста по дате рождения возникает в 1С постоянно: в кадровых отчётах, при проверке права на льготы, в печатных формах медицинских документов, при расчёте стажа. При этом встроенной функции «Возраст()» в языке 1С нет — разработчику нужно либо написать собственный алгоритм, либо использовать типовые механизмы конфигурации.

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

Ниже разобраны рабочие способы расчёта: универсальная функция на встроенном языке, использование типовых процедур из БСП и ЗУП, расчёт на произвольную дату и проверка результата на контрольных примерах.

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

Полный возраст в годах — это количество лет, прошедших с даты рождения, с поправкой на то, наступил ли день рождения в текущем (или заданном) году. Алгоритм состоит из трёх шагов: вычислить разность лет между датами, сравнить месяцы, при равенстве месяцев — сравнить дни.

Если месяц рождения больше текущего месяца, или месяцы равны, но день рождения больше текущего дня, — день рождения в этом году ещё не наступил, и из разности лет нужно вычесть единицу. Именно эту проверку чаще всего забывают, получая возраст на год больше фактического.

Для дат рождения 29 февраля в невисокосные годы стандартная практика — считать днём рождения 28 февраля либо 1 марта. В кадровом учёте это редко критично, но при юридически значимых расчётах (наступление совершеннолетия, пенсионный возраст) правило нужно зафиксировать в требованиях до написания кода.

Универсальная функция расчёта возраста на встроенном языке

Функция ниже принимает дату рождения и дату, на которую считается возраст (по умолчанию — текущая). Она не зависит от конфигурации и работает в любой базе на платформе 8.3.

Функция ВозрастВГодах(ДатаРождения, ДатаРасчета = Неопределено) Экспорт

Если Не ЗначениеЗаполнено(ДатаРождения) Тогда

Возврат 0;

КонецЕсли;

Если ДатаРасчета = Неопределено Тогда

ДатаРасчета = ТекущаяДатаСеанса();

КонецЕсли;

Возраст = Год(ДатаРасчета) - Год(ДатаРождения);

Если Месяц(ДатаРасчета) < Месяц(ДатаРождения)

Или (Месяц(ДатаРасчета) = Месяц(ДатаРождения)

И День(ДатаРасчета) < День(ДатаРождения)) Тогда

Возраст = Возраст - 1;

КонецЕсли;

Возврат Макс(Возраст, 0);

КонецФункции

Обратите внимание на защитные проверки: пустая дата рождения возвращает ноль вместо ошибки, а отрицательный результат (дата рождения в будущем) приводится к нулю через Макс(). Это важно для отчётов, где некорректные данные справочника не должны ронять весь расчёт.

Для расчёта возраста в месяцах (например, возраст ребёнка до года) логика аналогична: считается разность месяцев с поправкой на день, либо используется функция РазностьДат() с соответствующей единицей измерения и последующей корректировкой.

bsl
Возраст = Год(ТекущаяДата) - Год(ДатаРождения);
Если Месяц(ТекущаяДата) < Месяц(ДатаРождения)
    Или (Месяц(ТекущаяДата) = Месяц(ДатаРождения) И День(ТекущаяДата) < День(ДатаРождения)) Тогда
    Возраст = Возраст - 1;
КонецЕсли;

Типовые средства в конфигурациях на БСП и в ЗУП

Перед написанием собственной функции проверьте, нет ли готового механизма в конфигурации. В решениях на базе Библиотеки стандартных подсистем расчёт возраста встречается в общих модулях работы с датами и в кадровых подсистемах — точное имя функции зависит от версии библиотеки, поэтому ищите по слову «Возраст» в общих модулях через конфигуратор (Правка → Глобальный поиск).

В 1С:ЗУП возраст сотрудника используется в типовых отчётах и в механизме персональных данных. Для собственных отчётов на СКД проще всего вычислять возраст в запросе или в вычисляемом поле, а не дублировать код из кадровых модулей — так отчёт не сломается при обновлении конфигурации.

Если конфигурация не типовая и стандартных модулей нет, размещайте функцию расчёта в общем серверном модуле с признаком «Вызов сервера», чтобы она была доступна и из форм, и из фоновых заданий.

Расчёт возраста в запросе и в СКД

Когда возраст нужен в отчёте по списку сотрудников, вычислять его в цикле по строкам результата — плохая идея: это медленно и усложняет группировки. Правильнее посчитать возраст прямо в запросе или в вычисляемом поле СКД.

В языке запросов 1С есть функция РАЗНОСТЬДАТ(ДатаРождения, &ТекущаяДата, ГОД), но она даёт простую разность лет без учёта наступления дня рождения. Для точного результата добавьте условие через ВЫБОР: если месяц текущей даты меньше месяца рождения, или месяцы равны и день меньше — вычесть 1.

ВЫБОР

КОГДА МЕСЯЦ(&ТекущаяДата) < МЕСЯЦ(Сотрудники.ДатаРождения)

ИЛИ (МЕСЯЦ(&ТекущаяДата) = МЕСЯЦ(Сотрудники.ДатаРождения)

И ДЕНЬ(&ТекущаяДата) < ДЕНЬ(Сотрудники.ДатаРождения))

ТОГДА РАЗНОСТЬДАТ(Сотрудники.ДатаРождения, &ТекущаяДата, ГОД) - 1

ИНАЧЕ РАЗНОСТЬДАТ(Сотрудники.ДатаРождения, &ТекущаяДата, ГОД)

КОНЕЦ КАК Возраст

В СКД то же выражение можно вынести в вычисляемое поле и использовать в отборах — например, «сотрудники старше 50 лет». Учтите, что возраст в отчёте всегда считается на момент формирования; если нужен возраст на дату документа, передавайте эту дату параметром.

Порядок действий для отчёта на СКД
  1. 1
    Добавьте параметр ТекущаяДата (или ДатаОтчета) в набор данных
  2. 2
    Напишите выражение ВЫБОР с РАЗНОСТЬДАТ в запросе или вычисляемом поле
  3. 3
    Выведите поле Возраст в ресурсы или выбранные поля отчёта
  4. 4
    Проверьте отчёт на сотруднике, у которого день рождения завтра
  5. 5
    Проверьте группировки и отборы по возрасту

Расчёт возраста на произвольную дату и в документах

В документах возраст почти всегда нужен не «на сегодня», а на дату документа: возраст ребёнка на дату начала отпуска по уходу, возраст сотрудника на дату приказа. Поэтому функция расчёта обязательно должна принимать дату расчёта параметром, а не брать ТекущаяДатаСеанса() внутри.

Типичная ошибка — вычислять возраст при записи документа и сохранять его в реквизит. Через год документ показывает устаревшее значение, а перепроведение массово меняет исторические данные. Храните в базе дату рождения, а возраст вычисляйте в момент использования: в печатной форме, в отчёте, в проверке условий.

Исключение — случаи, когда возраст юридически фиксируется на момент события (например, возраст на дату страхового случая). Тогда сохранённое значение оправдано, но рядом всегда должна храниться и дата расчёта, чтобы значение было проверяемым.

Проверка результата и типичные ошибки

Проверяйте функцию на контрольных примерах до включения в прикладной код. Минимальный набор: человек, у которого день рождения сегодня (возраст должен увеличиться именно сегодня), человек с днём рождения завтра (возраст ещё не увеличился), дата рождения 29 февраля, дата рождения в будущем.

Контрольные точки

Как проверить результат

День рождения сегодня
Норма

Возраст увеличился на 1 по сравнению со вчерашним днём

Тревожный признак

Возраст меняется 1 января или не меняется в день рождения

День рождения завтра
Норма

Показывается возраст без учёта будущего дня рождения

Тревожный признак

Возраст уже увеличен на 1

Дата рождения пустая
Норма

Возвращается 0 или пустое значение без ошибки

Тревожный признак

Ошибка приведения типа или возраст больше 1000 лет

Дата рождения в будущем
Норма

Возвращается 0 без падения расчёта

Тревожный признак

Отрицательный возраст попадает в отчёт

Типичные ошибки
01
Деление разности дат на 365 — ошибка до года из-за високосных лет
02
Использование только РАЗНОСТЬДАТ(..., ГОД) без поправки на наступление дня рождения
03
Вызов ТекущаяДата() на клиенте — зависимость от часового пояса и настроек компьютера пользователя
04
Сохранение вычисленного возраста в реквизит — устаревание данных
05
Отсутствие обработки пустой даты рождения — падение отчёта на незаполненных карточках

Отдельно следите за различием ТекущаяДата() и ТекущаяДатаСеанса(). Первая на тонком клиенте возвращает время компьютера пользователя, вторая — время сервера. Для расчётов, влияющих на учёт, используйте дату сеанса или явно переданную дату документа, иначе у пользователей в разных часовых поясах результаты разойдутся.

Как вывести возраст с правильным склонением

В печатных формах возраст обычно нужен строкой: «35 лет», «41 год», «22 года». В БСП для этого есть функция склонения числительных (СтрокаСЧисломДляЛюбогоЯзыка или аналогичные механизмы представления), в простых случаях достаточно собственной функции по последней цифре числа.

Правило: если число оканчивается на 1 (кроме 11) — «год», на 2–4 (кроме 12–14) — «года», иначе — «лет». Исключения 11–14 проверяются по двум последним цифрам, иначе получится «11 год».

Функция ПредставлениеВозраста(Возраст) Экспорт

Остаток100 = Возраст % 100;

Если Остаток100 >= 11 И Остаток100 <= 14 Тогда

Возврат Строка(Возраст) + " лет";

КонецЕсли;

Остаток10 = Возраст % 10;

Если Остаток10 = 1 Тогда

Возврат Строка(Возраст) + " год";

ИначеЕсли Остаток10 >= 2 И Остаток10 <= 4 Тогда

Возврат Строка(Возраст) + " года";

Иначе

Возврат Строка(Возраст) + " лет";

КонецЕсли;

КонецФункции

Если возраст нужен только для проверки условия (например, «старше 18 лет»), не вычисляйте возраст вообще — сравните дату рождения с граничной датой: ДатаРождения <= ДобавитьМесяц(ДатаРасчета, -18 * 12). Такой код короче и не зависит от правил округления.
ПЗ
Практическое замечание

FAQ

Можно ли посчитать возраст простым делением разности дат на 365?

Нет. Из-за високосных лет и разного положения дня рождения внутри года такой расчёт даёт погрешность до одного года. Для кадровых и юридически значимых целей используйте сравнение месяца и дня рождения с датой расчёта.

Как посчитать возраст в месяцах для ребёнка?

Вычислите разность лет, умножьте на 12 и прибавьте разность месяцев. Если день расчёта меньше дня рождения, вычтите ещё один месяц. В запросе используйте РАЗНОСТЬДАТ с единицей МЕСЯЦ и аналогичную поправку на день.

Почему возраст в отчёте у разных пользователей отличается?

Скорее всего, используется ТекущаяДата() на клиенте — она берёт время компьютера пользователя, которое может отличаться по часовому поясу или быть сбитым. Перейдите на ТекущаяДатаСеанса() или передавайте дату расчёта параметром отчёта.

Как быть с датой рождения 29 февраля в невисокосный год?

Единого стандарта нет: в одних системах днём рождения считается 28 февраля, в других — 1 марта. Зафиксируйте выбранное правило в требованиях и реализуйте его явной проверкой, если случай юридически значим. В обычных кадровых отчётах разница в один день обычно не влияет на результат.

Нужно ли хранить возраст в карточке сотрудника?

Нет. Возраст меняется ежедневно, поэтому хранить нужно только дату рождения, а возраст вычислять в момент использования — в отчёте, печатной форме или проверке условия. Исключение — фиксация возраста на дату конкретного события, и тогда рядом хранится дата расчёта.

Как проверить условие «старше N лет» без вычисления возраста?

Сравните дату рождения с граничной датой: ДатаРождения <= ДобавитьМесяц(ДатаРасчета, -N * 12). Это короче, быстрее и не зависит от правил округления возраста.

Итог

Что важно запомнить

Возраст в 1С считается разностью лет с поправкой на наступление дня рождения: сравниваются месяц и день. В отчётах вычисляйте возраст в запросе или СКД, дату расчёта передавайте параметром, сам возраст не храните в базе. Проверяйте функцию на граничных случаях: день рождения сегодня, завтра и пустая дата.