Как в запросе 1С посчитать количество дней эксплуатации автомобиля с учетом заданного периода?

Программист 1С v8.3 (Управляемые формы) Управленческий учет
← На главную

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

Базовая математика дат: функция РАЗНОСТЬДАТ

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

РАЗНОСТЬДАТ(ДатаНачала, ДатаОкончания, ТипРазности)

Важно понимать, как именно система вычисляет результат. Если мы передаем в функцию две одинаковые даты (например, 01.01.2023 и 01.01.2023), функция вернет 0. Это происходит потому, что 1С (и лежащий в основе SQL-сервер) считает количество "границ" или переходов между датами. Для задач учета эксплуатации, где день начала и день окончания должны включаться в расчет, нам необходимо прибавлять единицу.

Посмотрим на пример простейшего кода в запросе:


ВЫБРАТЬ
    РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, ДЕНЬ) + 1 КАК КоличествоДней
ИЗ
    Справочник.Автомобили КАК Автомобили

Проблема учета времени в датах

Выясним причину, по которой расчет может выдавать странные результаты. В системе 1С тип Дата всегда содержит время. Если в параметре &ДатаОкончания передано значение "25.03.2022 00:00:00", а фактическая эксплуатация завершилась в конце дня, расчет может потерять целые сутки или выдать дробное значение при использовании других методов.

Чтобы гарантировать точность, разберем метод нормализации дат. Мы должны всегда приводить сравниваемые значения к началу дня. Проанализируем ситуацию: если мы используем функцию НАЧАЛОПЕРИОДА, мы обнуляем время, делая сравнение "чистым".

Рассмотрим более сложный, но универсальный метод расчета через секунды, который предложили участники обсуждения:


ВЫБРАТЬ
    (РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(&ДатаНачала, ДЕНЬ), КОНЕЦПЕРИОДА(&ДатаОкончания, ДЕНЬ), СЕКУНДА) + 1) / 86400 КАК Дни

В данном примере число 86400 — это количество секунд в сутках (24 * 3600). Такой подход позволяет избежать проблем с округлением, которые иногда возникают в различных СУБД (Microsoft SQL Server vs PostgreSQL).

Реализация сложной логики условий (Кейс из практики)

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

Рассмотрим три сценария:

  1. Машина куплена давно: считаем дни от &ДатаНачала до &ДатаОкончания.
  2. Машина куплена в середине периода: считаем от ДатаЭксплуатации до &ДатаОкончания.
  3. Машина куплена после окончания периода: результат должен быть 0.

Для реализации такой логики в запросе используем конструкцию ВЫБОР. Посмотрим на пример кода:


ВЫБРАТЬ
    Автомобиль,
    ВЫБОР
        // Если дата ввода позже конца периода - эксплуатации еще нет
        КОГДА ДатаЭксплуатации > &ДатаОкончания ТОГДА 0
        
        // Иначе вычисляем разницу между "Фактическим началом" и "Концом периода"
        ИНАЧЕ РАЗНОСТЬДАТ(
            ВЫБОР 
                КОГДА ДатаЭксплуатации > &ДатаНачала ТОГДА ДатаЭксплуатации 
                ИНАЧЕ &ДатаНачала 
            КОНЕЦ, 
            &ДатаОкончания, 
            ДЕНЬ) + 1
    КОНЕЦ КАК ДниВЭксплуатации
ИЗ
    Справочник.Автомобили

Разберем по шагам, что здесь происходит. Вложенный ВЫБОР определяет "точку старта". Если автомобиль уже работал на момент начала отчета, мы берем дату начала отчета. Если он был введен позже — берем дату ввода. Внешний ВЫБОР отсекает ситуации, когда эксплуатация еще не началась.

Особенности работы в Системе компоновки данных (СКД)

Если вы решаете задачу в СКД, проанализируем дополнительные возможности. В СКД можно использовать параметры типа СтандартныйПериод. Это удобно для пользователя, но в запросе нам все равно нужны отдельные даты.

Важные моменты для СКД:

Обработка исключительных ситуаций

Проанализируем ситуацию с "пустыми" датами. В 1С пустая дата — это 01.01.0001. Если в справочнике у автомобиля не заполнена ДатаЭксплуатации, функция РАЗНОСТЬДАТ вернет огромное число (количество дней от начала нашей эры), что приведет к ошибке в отчете.

Всегда добавляйте проверку на заполнение даты. В запросе это выглядит так:


ГДЕ
    ДатаЭксплуатации <> ДАТАВРЕМЯ(1, 1, 1)

Или обрабатывайте это внутри ВЫБОР, возвращая 0 при пустом значении. Это критически важно для стабильной работы информационной системы.

Резюме

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

← На главную