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

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

Базовые функции арифметики дат

Язык запросов 1С предоставляет разработчику набор предопределенных функций для работы с интервалами. Эти функции возвращают целое число, представляющее количество единиц времени между двумя моментами. Если вы пытаетесь передать строку или число, система выдаст ошибку типов.

Самой универсальной функцией является СЕКУНДРАЗНОСТЬ. Она возвращает количество секунд между двумя датами. Используя этот результат, можно получить любую другую величину, разделив её на соответствующий коэффициент. Например, для получения часов нужно разделить результат на 3600. Однако платформа предлагает и более специализированные функции, которые учитывают календарные особенности.

Для расчета полных дней часто используется ДНИРАЗНОСТЬ. Особенность этой функции в том, что она возвращает количество полных суток. Если разница составляет 23 часа 59 минут, функция вернет 0. Это фундаментальное отличие от простого деления секунд, которое может дать дробное число. Выбор правильной функции зависит от бизнес-логики вашего приложения.

💡

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

⚠️ Внимание: Функции разности дат чувствительны к временной зоне сервера. Если ваш сервер находится в одном часовом поясе, а пользователи работают в другом, при расчете интервалов, пересекающих переход через полночь, могут возникать смещения на час.

Расчет полных месяцев и лет

Вычисление разницы в месяцах или годах является более сложной задачей из-за неравномерной длины календарных периодов. В месяце может быть 28, 29, 30 или 31 день. Функция МЕСЯЦЕВРАЗНОСТЬ решает эту проблему, возвращая количество полных календарных месяцев между датами. Алгоритм учитывает не только номер месяца, но и день месяца.

Рассмотрим пример. Если дата начала — 31 января, а дата конца — 28 февраля (в невисокосный год), то разница составит 0 полных месяцев, так как 28 февраля еще не наступило 31 число. Только 1 марта разница станет равной 1 месяцу. Такое поведение часто удивляет новичков, ожидающих простого вычитания номеров месяцев.

Аналогично работает функция ЛЕТРАЗНОСТЬ. Она возвращает количество полных лет. Это особенно актуально при расчете возраста сотрудников или срока службы оборудования. Для получения точного стажа работы в годах и месяцах часто требуется комбинация этих функций или использование дополнительных вычислений в коде 1С после получения данных из запроса.

  • 📅 МЕСЯЦЕВРАЗНОСТЬ — возвращает целое число полных месяцев.
  • 📆 ЛЕТРАЗНОСТЬ — возвращает целое число полных лет.
  • ⏱️ СЕКУНДРАЗНОСТЬ — базовая функция для любых точных расчетов.
📊 Какая функция вызывает у вас больше всего вопросов?
СЕКУНДРАЗНОСТЬ
МЕСЯЦЕВРАЗНОСТЬ
ДНИРАЗНОСТЬ
РАБОЧИЕДНИРАЗНОСТЬ

Учет рабочих дней в расчетах

В бизнес-задачах часто требуется рассчитывать сроки не по календарным дням, а по рабочим. Для этого в языке запросов 1С существует функция РАБОЧИЕДНИРАЗНОСТЬ. Она принимает три аргумента: дата начала, дата конца и календарь рабочих дней. Календарь представляет собой ссылку на объект метаданных или таблицу значений, описывающую график работы.

Если третий параметр не указан или передан пустое значение, функция использует производственный календарь по умолчанию, установленный в конфигурации. Это позволяет автоматически исключать выходные (субботу и воскресенье) и праздничные дни из расчета. Однако для точной работы необходимо, чтобы в базе были корректно заполнены данные о переносах выходных дней.

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

⚠️ Внимание: Функция РАБОЧИЕДНИРАЗНОСТЬ работает медленнее обычных арифметических функций, так как требует обращения к регистру сведений о календаре. Избегайте её использования в запросах с выборкой десятков тысяч строк без острой необходимости.

Нюансы работы с календарем

Если календарь не найден или в нем есть разрывы, функция может вернуть NULL. Всегда проверяйте наличие записей в регистре "ГрафикиРаботыОрганизаций" перед использованием в массовых отчетах.

Сравнение дат в условиях отбора

Помимо вычисления разницы, часто требуется отобрать документы или записи регистра за определенный период. В секции ГДЕ языка запросов можно использовать стандартные операторы сравнения. Однако для динамических периодов, таких как "последние 7 дней" или "текущий месяц", удобно использовать функции дат прямо в условии.

Например, чтобы найти все документы, созданные более 30 дней назад, можно воспользоваться функцией НАЧАЛОПЕРИОДА в комбинации с вычитанием дней. Или же использовать ДОБАВИТЬКДАТЕ для формирования верхней границы интервала. Это позволяет делать запросы параметризированными и гибкими.

Частой ошибкой является попытка вычесть дату из даты прямо в условии ГДЕ без оборачивания в функцию разности. Хотя в некоторых версиях платформы это может сработать, правильный подход — использование СЕКУНДРАЗНОСТЬ(Дата1, Дата2) > Значение. Это гарантирует корректную работу механизма оптимизации запросов и использование индексов.

ВЫБРАТЬ

Документ.Ссылка,

Документ.Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

СЕКУНДРАЗНОСТЬ(ДОБАВИТЬКДАТЕ(СЕГОДНЯ(), -7, ДЕНЬ), Документ.Дата) > 0

☑️ Оптимизация запроса с датами

Выполнено: 0 / 4

Таблица функций работы с датами

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

Функция Возвращаемый тип Описание Пример использования
СЕКУНДРАЗНОСТЬ Число Разница в секундах Точный расчет длительности звонка
МИНУТЫРАЗНОСТЬ Число Разница в минутах Учет рабочего времени почасово
ДНИРАЗНОСТЬ Число Разница в полных днях Расчет просрочки платежа
МЕСЯЦЕВРАЗНОСТЬ Число Разница в полных месяцах Определение срока аренды
РАБОЧИЕДНИРАЗНОСТЬ Число Разница в рабочих днях Планирование сроков поставки

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

Обработка NULL и граничных значений

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

Для предотвращения такой ситуации рекомендуется использовать функцию ЕСТЬNULL или оператор IS NULL в условиях отбора. В селективной части запроса можно использовать конструкцию ВЫБОР..КОГДА..ТОГДА..КОНЕЦ, чтобы подставлять значение по умолчанию, например, 0, если одна из дат не заполнена.

Также стоит учитывать граничные значения типа Дата. Минимальная дата в 1С — это 1 января 1 года, а максимальная — 31 декабря 9999 года. При вычитании таких экстремальных значений может возникнуть переполнение, хотя в современных версиях платформы это обрабатывается корректно. Тем не менее, логика бизнеса редко требует оперирования такими промежутками.

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

💡

Всегда обрабатывайте возможные NULL-значения в полях дат перед вычислением разности, используя конструкцию ВЫБОР или функцию ЕСТЬNULL, чтобы избежать потери данных в отчетах.

Практические примеры и оптимизация

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

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

Если расчет разности дат используется для группировки данных (например, сгруппировать продажи по неделям), лучше предварительно округлить дату до начала недели с помощью функции НАЧАЛОПЕРИОДА. Это уменьшит количество уникальных значений в группе и ускорит работу механизма ГРУППИРОВКА.

ВЫБРАТЬ

Контрагент.Наименование,

МИНУМУМ(Документ.Дата) КАК ДатаПервогоДолга,

ДНИРАЗНОСТЬ(МИНУМУМ(Документ.Дата), &ТекущаяДата) КАК ДнейПросрочки

ИЗ

Документ.ПоступлениеТоваровУслуг КАК Документ

ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг.Оплата КАК Оплата

ПО Документ.Ссылка = Оплата.Ссылка

ГДЕ

Оплата.Ссылка ЕСТЬ NULL

ГРУППИРОВКА ПО

Контрагент.Наименование

Как получить дробное количество дней в запросе?

Для получения дробного значения (например, 1.5 дня) используйте функцию СЕКУНДРАЗНОСТЬ, а затем разделите результат на 86400 (количество секунд в сутках). Не забудьте привести тип деления к вещественному числу, умножив числитель или знаменатель на 1.0.

Почему МЕСЯЦЕВРАЗНОСТЬ возвращает 0 для интервала в 29 дней?

Функция считает полные календарные месяцы. Если разница меньше месяца (даже 29 дней в феврале), результат будет 0. Для получения дней используйте ДНИРАЗНОСТЬ.

Можно ли использовать разность дат в соединениях таблиц?

Да, можно. Например, соединять таблицы по условию, что даты отличаются не более чем на 5 минут. Однако такие соединения (не равнозначные) могут быть менее производительными, чем соединения по ключам.

Влияет ли високосный год на работу ДНИРАЗНОСТЬ?

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

Что делать, если дата конца меньше даты начала?

Функции разности дат вернут отрицательное число. Это нормальное поведение. Если вам нужен модуль разницы (всегда положительное число), используйте функцию АБС (абсолютное значение) вокруг выражения разности.