Разработка и Конфигурация · 11 мин
Как посчитать возраст в 1С: способы, код и проверка результата
Как посчитать возраст в 1С по дате рождения: готовые функции на встроенном языке, расчёт полных лет, учёт месяца и дня, типовые механизмы ЗУП и частые ошибки.
Задача вычисления возраста по дате рождения возникает в 1С постоянно: в кадровых отчётах, при проверке права на льготы, в печатных формах медицинских документов, при расчёте стажа. При этом встроенной функции «Возраст()» в языке 1С нет — разработчику нужно либо написать собственный алгоритм, либо использовать типовые механизмы конфигурации.
Главная сложность — корректная обработка граничных случаев: високосных лет, дня рождения 29 февраля, ситуации, когда день рождения в текущем году ещё не наступил. Простое деление разности дат на 365 даёт ошибку до одного года, поэтому такой подход в прикладных решениях недопустим.
Ниже разобраны рабочие способы расчёта: универсальная функция на встроенном языке, использование типовых процедур из БСП и ЗУП, расчёт на произвольную дату и проверка результата на контрольных примерах.
Как устроен правильный алгоритм расчёта возраста
Полный возраст в годах — это количество лет, прошедших с даты рождения, с поправкой на то, наступил ли день рождения в текущем (или заданном) году. Алгоритм состоит из трёх шагов: вычислить разность лет между датами, сравнить месяцы, при равенстве месяцев — сравнить дни.
Если месяц рождения больше текущего месяца, или месяцы равны, но день рождения больше текущего дня, — день рождения в этом году ещё не наступил, и из разности лет нужно вычесть единицу. Именно эту проверку чаще всего забывают, получая возраст на год больше фактического.
Для дат рождения 29 февраля в невисокосные годы стандартная практика — считать днём рождения 28 февраля либо 1 марта. В кадровом учёте это редко критично, но при юридически значимых расчётах (наступление совершеннолетия, пенсионный возраст) правило нужно зафиксировать в требованиях до написания кода.
Универсальная функция расчёта возраста на встроенном языке
Функция ниже принимает дату рождения и дату, на которую считается возраст (по умолчанию — текущая). Она не зависит от конфигурации и работает в любой базе на платформе 8.3.
Функция ВозрастВГодах(ДатаРождения, ДатаРасчета = Неопределено) Экспорт
Если Не ЗначениеЗаполнено(ДатаРождения) Тогда
Возврат 0;
КонецЕсли;
Если ДатаРасчета = Неопределено Тогда
ДатаРасчета = ТекущаяДатаСеанса();
КонецЕсли;
Возраст = Год(ДатаРасчета) - Год(ДатаРождения);
Если Месяц(ДатаРасчета) < Месяц(ДатаРождения)
Или (Месяц(ДатаРасчета) = Месяц(ДатаРождения)
И День(ДатаРасчета) < День(ДатаРождения)) Тогда
Возраст = Возраст - 1;
КонецЕсли;
Возврат Макс(Возраст, 0);
КонецФункции
Обратите внимание на защитные проверки: пустая дата рождения возвращает ноль вместо ошибки, а отрицательный результат (дата рождения в будущем) приводится к нулю через Макс(). Это важно для отчётов, где некорректные данные справочника не должны ронять весь расчёт.
Для расчёта возраста в месяцах (например, возраст ребёнка до года) логика аналогична: считается разность месяцев с поправкой на день, либо используется функция РазностьДат() с соответствующей единицей измерения и последующей корректировкой.
Возраст = Год(ТекущаяДата) - Год(ДатаРождения);
Если Месяц(ТекущаяДата) < Месяц(ДатаРождения)
Или (Месяц(ТекущаяДата) = Месяц(ДатаРождения) И День(ТекущаяДата) < День(ДатаРождения)) Тогда
Возраст = Возраст - 1;
КонецЕсли;Типовые средства в конфигурациях на БСП и в ЗУП
Перед написанием собственной функции проверьте, нет ли готового механизма в конфигурации. В решениях на базе Библиотеки стандартных подсистем расчёт возраста встречается в общих модулях работы с датами и в кадровых подсистемах — точное имя функции зависит от версии библиотеки, поэтому ищите по слову «Возраст» в общих модулях через конфигуратор (Правка → Глобальный поиск).
В 1С:ЗУП возраст сотрудника используется в типовых отчётах и в механизме персональных данных. Для собственных отчётов на СКД проще всего вычислять возраст в запросе или в вычисляемом поле, а не дублировать код из кадровых модулей — так отчёт не сломается при обновлении конфигурации.
Если конфигурация не типовая и стандартных модулей нет, размещайте функцию расчёта в общем серверном модуле с признаком «Вызов сервера», чтобы она была доступна и из форм, и из фоновых заданий.
Расчёт возраста в запросе и в СКД
Когда возраст нужен в отчёте по списку сотрудников, вычислять его в цикле по строкам результата — плохая идея: это медленно и усложняет группировки. Правильнее посчитать возраст прямо в запросе или в вычисляемом поле СКД.
В языке запросов 1С есть функция РАЗНОСТЬДАТ(ДатаРождения, &ТекущаяДата, ГОД), но она даёт простую разность лет без учёта наступления дня рождения. Для точного результата добавьте условие через ВЫБОР: если месяц текущей даты меньше месяца рождения, или месяцы равны и день меньше — вычесть 1.
ВЫБОР
КОГДА МЕСЯЦ(&ТекущаяДата) < МЕСЯЦ(Сотрудники.ДатаРождения)
ИЛИ (МЕСЯЦ(&ТекущаяДата) = МЕСЯЦ(Сотрудники.ДатаРождения)
И ДЕНЬ(&ТекущаяДата) < ДЕНЬ(Сотрудники.ДатаРождения))
ТОГДА РАЗНОСТЬДАТ(Сотрудники.ДатаРождения, &ТекущаяДата, ГОД) - 1
ИНАЧЕ РАЗНОСТЬДАТ(Сотрудники.ДатаРождения, &ТекущаяДата, ГОД)
КОНЕЦ КАК Возраст
В СКД то же выражение можно вынести в вычисляемое поле и использовать в отборах — например, «сотрудники старше 50 лет». Учтите, что возраст в отчёте всегда считается на момент формирования; если нужен возраст на дату документа, передавайте эту дату параметром.
- 1Добавьте параметр ТекущаяДата (или ДатаОтчета) в набор данных
- 2Напишите выражение ВЫБОР с РАЗНОСТЬДАТ в запросе или вычисляемом поле
- 3Выведите поле Возраст в ресурсы или выбранные поля отчёта
- 4Проверьте отчёт на сотруднике, у которого день рождения завтра
- 5Проверьте группировки и отборы по возрасту
Расчёт возраста на произвольную дату и в документах
В документах возраст почти всегда нужен не «на сегодня», а на дату документа: возраст ребёнка на дату начала отпуска по уходу, возраст сотрудника на дату приказа. Поэтому функция расчёта обязательно должна принимать дату расчёта параметром, а не брать ТекущаяДатаСеанса() внутри.
Типичная ошибка — вычислять возраст при записи документа и сохранять его в реквизит. Через год документ показывает устаревшее значение, а перепроведение массово меняет исторические данные. Храните в базе дату рождения, а возраст вычисляйте в момент использования: в печатной форме, в отчёте, в проверке условий.
Исключение — случаи, когда возраст юридически фиксируется на момент события (например, возраст на дату страхового случая). Тогда сохранённое значение оправдано, но рядом всегда должна храниться и дата расчёта, чтобы значение было проверяемым.
Проверка результата и типичные ошибки
Проверяйте функцию на контрольных примерах до включения в прикладной код. Минимальный набор: человек, у которого день рождения сегодня (возраст должен увеличиться именно сегодня), человек с днём рождения завтра (возраст ещё не увеличился), дата рождения 29 февраля, дата рождения в будущем.
Как проверить результат
Возраст увеличился на 1 по сравнению со вчерашним днём
Возраст меняется 1 января или не меняется в день рождения
Показывается возраст без учёта будущего дня рождения
Возраст уже увеличен на 1
Возвращается 0 или пустое значение без ошибки
Ошибка приведения типа или возраст больше 1000 лет
Возвращается 0 без падения расчёта
Отрицательный возраст попадает в отчёт
Отдельно следите за различием ТекущаяДата() и ТекущаяДатаСеанса(). Первая на тонком клиенте возвращает время компьютера пользователя, вторая — время сервера. Для расчётов, влияющих на учёт, используйте дату сеанса или явно переданную дату документа, иначе у пользователей в разных часовых поясах результаты разойдутся.
Как вывести возраст с правильным склонением
В печатных формах возраст обычно нужен строкой: «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С считается разностью лет с поправкой на наступление дня рождения: сравниваются месяц и день. В отчётах вычисляйте возраст в запросе или СКД, дату расчёта передавайте параметром, сам возраст не храните в базе. Проверяйте функцию на граничных случаях: день рождения сегодня, завтра и пустая дата.