При составлении запросов в 1С разработчики регулярно сталкиваются с вопросом: попадают ли записи, сделанные на граничную дату и время, в результат выборки? Поведение платформы различается в зависимости от того, к какой именно виртуальной таблице происходит обращение и какие конструкторские объекты или операторы применяются. Разберем детально логику обработки границ дат для таблиц остатков, оборотов и оператора МЕЖДУ.
Проанализируем работу с параметром периода в виртуальной таблице Остатки. По умолчанию, когда в параметр периода передается значение типа Дата или МоментВремени, платформа 1С рассчитывает остатки исключительно до указанного момента времени (не включая движения, записанные строго на эту секунду).
Например, если передать параметр &Дата1 = '31.01.2018 23:59:59' в параметр периода таблицы РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата1, ), то документы и записи, сделанные ровно в 31.01.2018 23:59:59, в результат расчета остатка не попадут.
Для того чтобы включить движения на граничную дату в расчет остатка, используют объект Граница с видом границы ВидГраницы.Включая.
// Передача объекта Граница с включением граничной даты
ГраницаПериода = Новый Граница(КонецДня(Дата1), ВидГраницы.Включая);
Запрос.УстановитьПараметр("Дата1", ГраницаПериода);
Если требуется получить остаток до или после проведения конкретного документа, передают момент времени документа с нужным видом границы:
// Остаток ПОСЛЕ проведения документа (с учетом его собственных движений)
ГраницаПосле = Новый Граница(Ссылка.МоментВремени(), ВидГраницы.Включая);
Запрос.УстановитьПараметр("Период", ГраницаПосле);
Рассмотрим распространенный альтернативный вариант получения остатков на конец дня без использования объекта Граница: прибавление одной секунды к дате. Передавая в параметр периода начало следующего дня (например, 01.02.2018 00:00:00), мы гарантируем, что платформа рассчитает остаток до этой секунды, то есть учтет все записи за 31.01.2018 23:59:59 включительно.
// Альтернатива: смещение на начало следующего дня
Запрос.УстановитьПараметр("Период", КонецДня(Дата1) + 1);
Выясним, как ведет себя виртуальная таблица Обороты. В отличие от остатков, параметры НачалоПериода и КонецПериода в таблице оборотов работают по правилу полного включения границ по умолчанию.
Передаваемые значения типа Дата и МоментВремени включаются в выборку. Это означает, что при обращении РегистрНакопления.ТоварыНаСкладах.Обороты(&Дата1, &Дата2, Запись, ) записи с временем &Дата1 и &Дата2 полностью попадают в рассчитываемые обороты.
Разберем специфику работы комбинированной виртуальной таблицы ОстаткиИОбороты:
>=).<=) как для расчета оборотов, так и для расчета конечного остатка.Посмотрим на применение оператора МЕЖДУ при фильтрации по датам (например, ПланыПродаж.Период МЕЖДУ &Дата1 И &Дата2). Конструкция Поле МЕЖДУ &Дата1 И &Дата2 эквивалентна условию Поле >= &Дата1 И Поле <= &Дата2. Из этого следует, что обе границы берется **включительно**.
Однако при работе с оператором МЕЖДУ важно правильно подготавливать параметры во встроенном языке BSL:
&Дата2 передана дата без времени (например, '20180131'), платформа подставит '31.01.2018 00:00:00'. В результате документы, оформленные в течение дня 31 января, не попадут в условие.&Дата2 необходимо приводить к концу дня с помощью функции КонецДня().
// Правильная подготовка параметров для оператора МЕЖДУ
Запрос.УстановитьПараметр("Дата1", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("Дата2", КонецДня(ДатаОкончания));
Проанализируем ключевые особенности применения параметров периода на практике:
Граница или МоментВремени в параметр запроса можно только из кода на BSL с помощью метода УстановитьПараметр().Граница, МоментВремени) в виртуальных таблицах на больших объемах данных может снижать скорость выполнения запроса по сравнению с типом Дата. Это связано с усложнением алгоритмов сопоставления движений и итогов СУБД. В задачах построения отчетов зачастую предпочтительнее передавать сдвинутую дату (КонецДня(Дата) + 1).