Как в 1С рассчитать стаж и разницу дат в годах, месяцах и днях

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При разработке кадровых отчетов и обработок часто возникает задача определить точный стаж сотрудника или интервал между двумя датами с выводом результата в формате «N лет, N месяцев, N дней». Попытка решить эту задачу исключительно средствами языка запросов 1С сталкивается с серьезными ограничениями. Разберем, почему чистый расчет в запросе не дает точного результата, и рассмотрим правильные варианты реализации на встроенном языке и в схеме компоновки данных (СКД).

Ограничения языка запросов и функции РАЗНОСТЬДАТ

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

Проанализируем пример: если вычислить разность дат между 31 января и 1 февраля с типом МЕСЯЦ, функция вернет значение 1, хотя фактически между датами прошел всего один календарный день. Аналогично возникают расхождения при переходе через високосные года и месяцы с разным количеством дней (28, 29, 30 и 31 день).

Попытка выразить стаж в днях через запрос с последующим делением:


ВЫБОР
	КОГДА Сотрудники.ДатаУвольнения = ДАТАВРЕМЯ(1, 1, 1)
		ТОГДА РАЗНОСТЬДАТ(Сотрудники.ДатаПриема, &ТекущаяДата, ДЕНЬ)
	ИНАЧЕ РАЗНОСТЬДАТ(Сотрудники.ДатаПриема, Сотрудники.ДатаУвольнения, ДЕНЬ)
КОНЕЦ КАК ДнейСтажа

Такой подход дает лишь приблизительное число дней. При обратном переводе в годы и месяцы (делением на 365 или 30) неизбежно накапливаются ошибки, которые не согласуются с официальными правилами кадрового учета.

Алгоритм точного расчета на встроенном языке

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

Рассмотрим по шагам реализацию универсальной функции:

  1. Приводим даты к началу дня для исключения влияния времени.
  2. Последовательно увеличиваем начальную дату на 12 месяцев (1 год), пока она не превысит конечную дату, и фиксируем количество полных лет.
  3. Затем увеличиваем полученную дату по 1 месяцу, пока она не превысит конечную дату, и фиксируем количество полных месяцев.
  4. Оставшуюся разницу вычисляем в днях путем прямого вычитания дат (в 1С разность дат возвращает количество секунд, которое делим на 86 400).

Посмотрим на пример кода функции:


Функция ПолучитьСтажПрописью(Знач ДатаНачала, Знач ДатаОкончания) Экспорт

	Если Не ЗначениеЗаполнено(ДатаНачала) Тогда
		Возврат "";
	КонецЕсли;

	Если Не ЗначениеЗаполнено(ДатаОкончания) Тогда
		ДатаОкончания = ТекущаяДатаСеанса();
	КонецЕсли;

	ДатаСч = НачалоДня(ДатаНачала);
	// Включаем день окончания в стаж (+1 день)
	ДатаКон = НачалоДня(ДатаОкончания) + 86400; 

	Если ДатаСч >= ДатаКон Тогда
		Возврат "0 лет 0 мес 0 дн";
	КонецЕсли;

	Лет = 0;
	Месяцев = 0;

	// Считаем полные годы
	Пока ДобавитьМесяц(ДатаСч, 12) <= ДатаКон Цикл
		Лет = Лет + 1;
		ДатаСч = ДобавитьМесяц(ДатаСч, 12);
	КонецЦикла;

	// Считаем полные месяцы
	Пока ДобавитьМесяц(ДатаСч, 1) <= ДатаКон Цикл
		Месяцев = Месяцев + 1;
		ДатаСч = ДобавитьМесяц(ДатаСч, 1);
	КонецЦикла;

	// Оставшиеся дни
	Дней = (ДатаКон - ДатаСч) / 86400;

	Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		"%1 г. %2 мес. %3 дн.",
		Формат(Лет, "ЧГ=0"),
		Формат(Месяцев, "ЧГ=0"),
		Формат(Дней, "ЧГ=0")
	);

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

Использование готовых функций БСП и типовых конфигураций

В конфигурациях, использующих Библиотеку Стандартных Подсистем (БСП), а также в 1С:ЗУП, 1С:ERP и 1С:КА, нет необходимости писать алгоритм с нуля. В типовом общем модуле ОбщегоНазначенияКлиентСервер или специализированных модулях кадрового учета доступны готовые функции (например, ПериодВГодахМесяцахДнях), которые возвращают структуру с полями Лет, Месяцев, Дней либо сразу формируют строковое представление.

Вывод стажа в отчетах схемы компоновки данных (СКД)

Если отчет строится на СКД, оптимальным решением является получение «сырых» дат в запросе и их форматирование через вычисляемые поля с вызовом функции общего модуля.

Разберем порядок настройки:

  1. В запросе набора данных выбираем исходные поля: ДатаПриема и ДатаУвольнения.
  2. Создаем экспортную функцию в общем модуле (модуль должен иметь установленные флаги Сервер, Внешнее соединение и Вызов сервера, либо быть клиент-серверным).
  3. В схеме компоновки данных переходим на вкладку Вычисляемые поля.
  4. Добавляем новое поле СтажСтрокой и в колонке Выражение указываем вызов функции:

ИмяВашегоОбщегоМодуля.ПолучитьСтажПрописью(ДатаПриема, Выбор Когда ДатаУвольнения = ДАТАВРЕМЯ(1,1,1) Тогда &Период Иначе ДатаУвольнения Конец)

Таким образом, запрос остается простым и производительным, а вся логика работы с календарем и високосными годами безошибочно выполняется на встроенном языке 1С.

← На главную