При разработке отчетов или обработок в 1С часто возникает задача: нужно разбить заданный пользователем период на отдельные дни и получить для каждого дня точное время его начала (00:00:00) и конца (23:59:59). Проанализируем ситуацию: у нас есть дата начала периода и дата окончания. Нам необходимо сформировать список дат, где каждая строка будет содержать начало и конец конкретного дня. Разберем по шагам, как это можно реализовать различными способами, от простого перебора до использования языка запросов и Библиотеки стандартных подсистем (БСП).
Самый простой и понятный подход, не требующий обращения к базе данных — это перебор дней в цикле. Мы вычислим количество дней в заданном интервале и с помощью функций НачалоДня и КонецДня получим нужные нам значения. Посмотрим на пример реализации данного алгоритма:
ДатаНачалаПериода = Дата(2023, 4, 1, 0, 0, 0); // 01.04.2023
ДатаОкончанияПериода = Дата(2023, 4, 30, 23, 59, 59); // 30.04.2023
ТекущаяДата = НачалоДня(ДатаНачалаПериода);
КонечнаяДата = КонецДня(ДатаОкончанияПериода);
// Вычисляем количество дней в периоде (прибавляем 1 секунду для корректности)
КоличествоДней = (КонечнаяДата - ТекущаяДата + 1) / (24 * 60 * 60);
Для i = 1 По КоличествоДней Цикл
ТекущееНачало = НачалоДня(ТекущаяДата);
ТекущийКонец = КонецДня(ТекущаяДата);
Сообщить("Начало: " + Строка(ТекущееНачало) + " - Конец: " + Строка(ТекущийКонец));
// Переходим к следующему дню
ТекущаяДата = ТекущаяДата + 24 * 60 * 60;
КонецЦикла;
В этом примере мы используем математическое вычисление количества секунд в дне (24 * 60 * 60). Метод работает крайне быстро и не создает нагрузки на сервер базы данных. Это оптимальный вариант, если результат нужен только на клиенте или сервере для дальнейшей программной обработки.
Иногда гонять данные между сервером 1С и СУБД в виде коллекций нерационально. Если список дат нужен нам для того, чтобы соединить его с другой таблицей в запросе (например, со срезом последних регистра сведений на каждый день), лучше сгенерировать этот список прямо в самом запросе. Выясним причину: в языке запросов 1С нет прямого аналога функции генерации серий. Однако мы можем воспользоваться готовой таблицей в базе.
Рассмотрим использование физической таблицы регистра сведений ДанныеПроизводственногоКалендаря или КалендарныеГрафики:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(ДанныеКалендаря.ДатаГрафика, ДЕНЬ) КАК НачалоДня,
КОНЕЦПЕРИОДА(ДанныеКалендаря.ДатаГрафика, ДЕНЬ) КАК КонецДня
ИЗ
РегистрСведений.ДанныеПроизводственногоКалендаря КАК ДанныеКалендаря
ГДЕ
ДанныеКалендаря.ДатаГрафика МЕЖДУ &НачалоПериода И &КонецПериода
Передав параметры &НачалоПериода и &КонецПериода в этот запрос, мы сразу получим выборку с нужными границами каждого дня. Главное преимущество этого метода — отсутствие циклов в коде и возможность напрямую связать полученную таблицу (используя ЛЕВОЕ СОЕДИНЕНИЕ) с любыми другими данными в том же запросе.
В конфигурациях, основанных на Библиотеке стандартных подсистем, таких как ERP, Комплексная автоматизация (КА) и ЗУП, есть готовые методы для решения нашей задачи. Разработчики 1С активно используют их для механизмов представлений. Рассмотрим подробнее.
Вы можете найти общие модули, содержащие функции вроде ЗапросВТПериоды или СоздатьВТПериоды. Эти процедуры генерируют временную таблицу со списком дат. Обычно они принимают на вход даты начала и окончания, а также периодичность (день, неделя, месяц). В результате работы такой функции во временных таблицах менеджера запроса появляется таблица с периодами, которую затем можно использовать в своих отчетах.
Важно отметить: использование универсальных функций БСП иногда может излишне перегружать систему. Данные могут собираться на стороне SQL, передаваться на сервер 1С в коллекцию, переформатироваться и отправляться обратно. Если вам не требуется сложная логика производственных календарей (учет выходных/праздничных дней), а нужны просто календарные сутки, написание 10-15 строк кода циклом с использованием НачалоДня и КонецДня может оказаться более оптимальным и читаемым решением.
Подведем итог. Для решения задачи вывода начала и конца дня за интервал у вас есть три основных пути:
ЗапросВТПериоды (если вы работаете в рамках архитектуры современных типовых конфигураций).