В практике программирования на платформе 1С:Предприятие 8.3, особенно в конфигурациях «Зарплата и Управление Персоналом», часто возникает задача вычисления точного стажа сотрудника или периода работы в должности. Казалось бы, простая задача вычитания одной даты из другой осложняется тем, что календарные месяцы имеют разную длительность, существуют високосные годы, а результат необходимо представить в человекочитаемом формате: «количество лет, месяцев и дней».
В этой статье мы подробно разберем, как решить эту задачу максимально эффективно, используя как встроенные механизмы Библиотеки стандартных подсистем (БСП), так и специализированные функции кадрового учета ЗУП.
Если вы работаете в современной конфигурации на базе БСП (а ЗУП 3.1 к ним относится), нет необходимости изобретать велосипед и писать сложные алгоритмы с перебором месяцев. Разработчики фирмы «1С» уже предусмотрели «кошерный» способ получения разности дат. Мы рекомендуем использовать функцию из общего модуля ОбщегоНазначенияКлиентСервер.
Рассмотрим применение функции РазностьДатовФорматеГМД. Она возвращает структуру, содержащую готовые числовые значения лет, месяцев и дней.
Пример реализации кода:
ДатаНачала = Объект.ДатаПриема; // Например, 01.01.2020
ДатаКонца = ТекущаяДата();
Разность = ОбщегоНазначенияКлиентСервер.РазностьДатовФорматеГМД(ДатаНачала, ДатаКонца);
Лет = Разность.Лет;
Месяцев = Разность.Месяцев;
Дней = Разность.Дней;
Сообщить(СтрШаблон("Сотрудник работает: %1 лет, %2 месяцев, %3 дней", Лет, Месяцев, Дней));
Преимущество этого метода заключается в том, что он доступен как на стороне сервера, так и на стороне клиента, и корректно учитывает все календарные нюансы. Проанализируем результат: функция возвращает структуру с ключами Лет, Месяцев и Дней, что позволяет сразу использовать эти данные в программной логике или выводить их в отчет. Если требуется готовый печатный документ по стажу без самостоятельной разработки, можно использовать внешний отчет для формирования справки о стаже сотрудников в ЗУП.
В конфигурации 1С:ЗУП существуют еще более специфические функции, которые предназначены именно для расчета стажа. Важно понимать, что в кадровом учете часто применяется правило «включительности»: день увольнения или текущий день считается рабочим, поэтому к разности дат иногда нужно добавлять один день.
Для этих целей в ЗУП предусмотрен модуль КадровыйУчетКлиентСервер (или КадровыйУчет в более ранних версиях). Посмотрим, как вызвать аналогичную функцию из этого контекста:
// В ЗУП 3.1 часто используется аналогичная структура вызова
РезультатСтажа = КадровыйУчетКлиентСервер.РазностьДатовФорматеГМД(ДатаНачала, ДатаОкончания);
// Результат аналогичен - структура с полями Лет, Месяцев, Дней
Если же ваша задача — не просто получить цифры, а вывести красивую строку для печатной формы (например, для личной карточки Т-2), воспользуемся методом получения строкового представления:
ТекстСтажа = КадровыйУчет.ПредставлениеСтажа(Разность.Лет, Разность.Месяцев, Разность.Дней);
// Вернет строку вида "5 лет 2 месяца 10 дней"
Иногда требуется получить не просто количество времени, а красиво оформленный период. В составе БСП есть функция, которая делает это автоматически, соблюдая правила склонения числительных в русском языке.
Разберем использование модуля СтроковыеФункцииКлиентСервер:
ДатаНачала = '20210101';
ДатаКонца = '20230520';
// Функция сформирует строку с правильными окончаниями (год/года/лет)
СтрокаПериода = СтроковыеФункцииКлиентСервер.ПредставлениеПериода(ДатаНачала, ДатаКонца, "ЛМД");
// Результат: "2 года, 4 месяца, 19 дней"
Здесь параметр "ЛМД" указывает системе, что мы хотим видеть именно Лет, Месяцев и Дней. Это избавляет программиста от необходимости писать громоздкие условия Если Число % 10 = 1 Тогда... для правильного вывода окончаний слов.
Если по каким-то причинам вы работаете в старой версии платформы или в конфигурации, где БСП сильно ограничена, можно реализовать алгоритм «вручную». Основная сложность здесь — расчет переходов через границы месяцев.
Проанализируем логику такого расчета по шагам:
ДобавитьМесяц в цикле или через разность календарных компонентов.Цел(КолвоМесяцев / 12).КолвоМесяцев % 12.Пример кода для ручного расчета:
Функция ПолучитьРазностьГМД(Дата1, Дата2) Экспорт
Если Дата1 > Дата2 Тогда
ВремДата = Дата1;
Дата1 = Дата2;
Дата2 = ВремДата;
КонецЕсли;
Лет = 0; Месяцев = 0; Дней = 0;
// Считаем годы
ВременнаяДата = Дата1;
Пока ДобавитьМесяц(ВременнаяДата, 12) <= Дата2 Цикл
Лет = Лет + 1;
ВременнаяДата = ДобавитьМесяц(ВременнаяДата, 12);
КонецЦикла;
// Считаем месяцы
Пока ДобавитьМесяц(ВременнаяДата, 1) <= Дата2 Цикл
Месяцев = Месяцев + 1;
ВременнаяДата = ДобавитьМесяц(ВременнаяДата, 1);
КонецЦикла;
// Остаток - это дни
Дней = (НачалоДня(Дата2) - НачалоДня(ВременнаяДата)) / 86400;
Результат = Новый Структура("Лет, Месяцев, Дней", Лет, Месяцев, Дней);
Возврат Результат;
КонецФункции
Этот метод считается более медленным из-за циклов, но он наглядно показывает математику процесса. В промышленной эксплуатации в ЗУП 3.1 всегда лучше отдавать предпочтение Методу №1.
При работе с датами в 1С:ЗУП следует помнить о нескольких критически важных моментах:
Дата содержит время. Если вы сравниваете '2023-01-01 00:00:00' и '2023-01-01 23:59:59', для системы это один и тот же день, но разница в секундах может повлиять на расчет. Всегда используйте НачалоДня() для обеих дат перед расчетом стажа.РАЗНОСТЬДАТ(Дата1, Дата2, МЕСЯЦ) считает количество границ месяцев. Это значит, что между 31 января и 1 февраля разница будет 1 месяц, хотя прошел всего один день. Для получения точного ГМД в запросах обычно рассчитывают общее количество дней, а затем преобразуют его в программном коде при выводе результата.Подводя итог, можно сказать: для решения задачи в ЗУП самым правильным и надежным способом является вызов ОбщегоНазначенияКлиентСервер.РазностьДатовФорматеГМД(). Это гарантирует соответствие стандартам разработки 1С и корректность кадровых отчетов. Для комплексного анализа кадрового состава на предприятии можно использовать сводный отчет по стажу сотрудников.