Как правильно вычислить разницу дат в вычисляемых полях СКД?

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

Разберем частую задачу, с которой сталкиваются разработчики при проектировании отчетов в Системе Компоновки Данных (СКД). Представим ситуацию: необходимо вычислить остаток дней отпуска с использованием вычисляемых полей. Автор исходной задачи попытался использовать прямое арифметическое вычитание дат, например ТекущаяДата - НачалоГода, но столкнулся с ошибкой применения оператора «минус» к датам. Проанализируем причину такого поведения и рассмотрим корректные пути решения.

Почему возникает ошибка при вычитании дат в СКД

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

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

Решение проблемы через функцию РАЗНОСТЬДАТ

Первоначальный вариант, предложенный для решения проблемы, заключался в переводе дат в секунды и последующем математическом преобразовании. Код выглядел следующим образом:


РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ТекущаяДата(), "ГОД"), ТекущаяДата(), "СЕКУНДА") * 20 / 31536000 - ЕСТЬNULL(ОтпускИТОГО, 0)

Здесь вычисляется разница в секундах, которая потом делится на количество секунд в невысокосном году (31 536 000). Хотя это выражение синтаксически верно, оно сложно для восприятия и таит в себе логические ошибки.

Оптимизация формулы: работа с днями

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

РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ТекущаяДата(), "ГОД"), ТекущаяДата(), "ДЕНЬ")

Такой код гораздо легче читать и поддерживать.

Решение проблемы високосного года

Проанализируем ситуацию с високосными годами. Если жестко зафиксировать количество дней в году как 365, то каждый високосный год вычисления будут давать погрешность. Вместо этого в СКД можно динамически определять длину текущего года. Разберем по шагам, как это сделать:


РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ТекущаяДата(), "ГОД"), КОНЕЦПЕРИОДА(ТекущаяДата(), "ГОД"), "ДЕНЬ") + 1

Это выражение автоматически вернет 365 для обычного года и 366 для високосного. Теперь мы можем использовать эту динамическую базу для любых пропорциональных вычислений.

Использование параметров вместо системной даты

Обратим внимание на функцию ТекущаяДата(). В выражениях СКД она возвращает дату компьютера на момент генерации отчета. Это жестко ограничивает пользователя: он не сможет посмотреть остатки отпусков ретроспективно, например, на конец прошлого квартала.

Разумнее использовать глобальный параметр отчета (например, &Период). Посмотрим на пример оптимизированной формулы:

РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&Период, "ГОД"), &Период, "ДЕНЬ")

В этом случае пользователь сам задает нужную дату на форме отчета, что делает решение гибким.

Функция ЕСТЬNULL в языке выражений СКД

В выражениях СКД проверка на пустые значения отличается от языка запросов. Использование конструкции ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ перегружает текст формулы. Намного эффективнее использовать специализированную функцию:

ЕСТЬNULL(ОтпускИТОГО, 0)

Эта компактная запись корректно преобразует пустое значение в ноль.

Ошибки бизнес-логики: как правильно считать отпуска

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

  1. Рабочий год вместо календарного: По Трудовому Кодексу РФ право на отпуск рассчитывается не с 1 января (календарный год), а за рабочий год конкретного сотрудника. Рабочий год отсчитывается с даты его приема на работу. Следовательно, использование НачалоГода() в данной задаче методологически неверно. В формулу должна подставляться дата приема сотрудника.
  2. Норма дней: Стандартная норма отпуска составляет 28 календарных дней за полный рабочий год. За каждый отработанный месяц начисляется 2.33 дня. Использование в формуле коэффициентов вроде «20 дней» допустимо только при очень специфичной локальной нормативной базе предприятия.
  3. Использование типовых решений: Напомним, что для учета отпусков, стажа и отсутствий существует типовая конфигурация 1С:Зарплата и Управление Персоналом. Прежде чем писать сложную логику «с нуля», стоит рассмотреть возможность использования стандартных регистров сведений и накопления, где эта информация уже рассчитана корректно.

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

← На главную