Синтаксис и применение Дополнение дат в платформе 1С:Предприятие. Описание и примеры кода.
Полное описание, параметры и ограничения
Дополнение дат
В случае если поле, по которому рассчитываем итоги, является полем типа Дата то возможно дополнение результатов датами в заданном периоде. Делается это при помощи ключевого слова ПЕРИОДАМИ, после которого в скобках указывается вид периода (одно из СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД, ДЕКАДА, ПОЛУГОДИЕ), начальная и конечные даты интересуемого периода. В случае если начальные и конечные даты не указаны, будут использованы первая и последние даты, участвующие в результате.
Пример:
// Получить количество продаж по клиентам по месяцам
ВЫБРАТЬ Получатель, НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) КАК Период, КОЛИЧЕСТВО(Ссылка) КАК КоличествоПокупок
ИЗ Документ.РасхНакл
СГРУППИРОВАТЬ ПО Получатель, НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ)
ИТОГИ СУММА(КоличествоПокупок) ПО Период ПЕРИОДАМИ(Месяц, ДАТАВРЕМЯ(2000, 07, 01), ДАТАВРЕМЯ(2000, 12, 01))
Результат запроса:
Получатель
Период
КоличествоПокупок
01.07.2000 0:00:00
3
Маг. "Мебель"
01.07.2000 0:00:00
1
Урюпинскторг
01.07.2000 0:00:00
1
Маг. "Хозяин"
01.07.2000 0:00:00
1
01.08.2000 0:00:00
1
Маг. "Гигант"
01.08.2000 0:00:00
1
01.09.2000 0:00:00
1
Урюпинскторг
01.09.2000 0:00:00
1
01.10.2000 0:00:00
0
01.11.2000 0:00:00
0
01.12.2000 0:00:00
0
Такое представление результата получится, только если при обходе результата по группировке "Период" использовать в качестве источника измерения все записи "Период"-а.
Практические примеры
ПЕРИОДАМИ: получить четыре месяца и отличить дополненный итог от детали
Три собственные датированные строки дают две строки результата: январь/5 и март/4. Итоги дополняются февралём и апрелем. Полный обход проверяет все месяцы и вложенные детали, а неопределённый справкой сырой ресурс пустого месяца показывает фактически.
Где и как запускать
Полный серверный общий модуль отдельной учебной базы 8.5.1.1343. Только свои строки в памяти и приватная временная таблица; запросы в 1С здесь не запускались. Сырой ресурс пустого итога определяется будущим ручным опытом, не Python-моделью.
Подготовка
В отдельной учебной базе 8.5.1.1343 создайте общий модуль УчебныйЯзык: Сервер=Истина, Глобальный=Ложь, ВызовСервера=Ложь, Привилегированный=Ложь. Клиентские и внешнее соединение отключены; ПовторноеИспользованиеВозвращаемыхЗначений=НеИспользовать.
Вставьте весь приведённый текст в этот общий модуль. ВыполнитьПример — экспортная точка входа; остальные процедуры и функции располагаются рядом, а не внутри неё.
В своей внешней учебной обработке создайте управляемую форму, команду Выполнить и кнопку. Клиентский обработчик Выполнить(Команда) вызывает свою процедуру ВыполнитьНаСервере(); она имеет директиву &НаСервереБезКонтекста и одну строку УчебныйЯзык.ВыполнитьПример();. Это серверный вызов общего модуля, а не разрешение клиенту прямо обращаться к серверной библиотеке.
Все товары, количества и строки придуманы в этом модуле. Запись документов, подключение к чужой базе, файлы, сеть и печать не используются. В рабочие общие модули текст не вставляйте.
HTML только показывает BSL. Код в 1С не запускался; перечисленные результаты и отрицательные опыты проверяйте самостоятельно в собственном стенде.
Не нужны справочники, документы, регистры, записанные объекты или собственная схема метаданных: источник полностью создаётся кодом. Все помощники этого опыта предоставлены в том же полном модуле.
Две проверки границ и девять ожидаемых отказов проверяют только собственный валидатор без присваивания в типизированную таблицу. Рабочая таблица содержит строго три явно заданные корректные строки.
При ручном запуске сохраните фактические сообщения о сыром ресурсе февраля и апреля вместе с типами. Код намеренно не подменяет их ожидаемыми нулями и не сообщает о выполнении, которого здесь не было.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвоюВходнуюСтроку(Дата(2026, 1, 1), 0);
ПроверитьСвоюВходнуюСтроку(Дата(2026, 4, 1), 9999);
ПроверитьОтклонениеСвоегоВвода(Неопределено, 2);
ПроверитьОтклонениеСвоегоВвода("2026-01-15", 2);
ПроверитьОтклонениеСвоегоВвода(Дата(2025, 12, 31, 23, 59, 59), 2);
ПроверитьОтклонениеСвоегоВвода(Дата(2026, 4, 1, 0, 0, 1), 2);
ПроверитьОтклонениеСвоегоВвода(Дата(2026, 1, 15), Неопределено);
ПроверитьОтклонениеСвоегоВвода(Дата(2026, 1, 15), "2");
ПроверитьОтклонениеСвоегоВвода(Дата(2026, 1, 15), -1);
ПроверитьОтклонениеСвоегоВвода(Дата(2026, 1, 15), 10000);
ПроверитьОтклонениеСвоегоВвода(Дата(2026, 1, 15), 2.5);
Источник = СоздатьСвойИсточникДат();
ДобавитьСвоюСтрокуДаты(Источник, Дата(2026, 1, 15), 2);
ДобавитьСвоюСтрокуДаты(Источник, Дата(2026, 1, 20), 3);
ДобавитьСвоюСтрокуДаты(Источник, Дата(2026, 3, 7), 4);
Ожидание = Новый Массив;
Ожидание.Добавить(Новый Структура("Период,СуммаДеталей,КоличествоДеталей", Дата(2026, 1, 1), 5, 1));
Ожидание.Добавить(Новый Структура("Период,СуммаДеталей,КоличествоДеталей", Дата(2026, 2, 1), 0, 0));
Ожидание.Добавить(Новый Структура("Период,СуммаДеталей,КоличествоДеталей", Дата(2026, 3, 1), 4, 1));
Ожидание.Добавить(Новый Структура("Период,СуммаДеталей,КоличествоДеталей", Дата(2026, 4, 1), 0, 0));
Если Источник.Количество() <> 3 Или Источник.Колонки.Количество() <> 2 Тогда
ВызватьИсключение "Собственный источник должен содержать три строки и два типизированных столбца";
КонецЕсли;
Менеджер = Новый МенеджерВременныхТаблиц;
Попытка
Создание = Новый Запрос;
Создание.МенеджерВременныхТаблиц = Менеджер;
Создание.Текст = "ВЫБРАТЬ Данные.Дата КАК Дата, Данные.Количество КАК Количество
|ПОМЕСТИТЬ ВТСобственныеДаты
|ИЗ &Источник КАК Данные";
Создание.УстановитьПараметр("Источник", Источник);
Создание.Выполнить();
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Менеджер;
Запрос.Текст = "ВЫБРАТЬ
| НАЧАЛОПЕРИОДА(Данные.Дата, МЕСЯЦ) КАК Период,
| СУММА(Данные.Количество) КАК Количество
|ИЗ ВТСобственныеДаты КАК Данные
|СГРУППИРОВАТЬ ПО НАЧАЛОПЕРИОДА(Данные.Дата, МЕСЯЦ)
|ИТОГИ СУММА(Количество)
|ПО Период ПЕРИОДАМИ(МЕСЯЦ, ДАТАВРЕМЯ(2026, 1, 1), ДАТАВРЕМЯ(2026, 4, 1))";
Результат = Запрос.Выполнить();
ПроверитьДвеИсходныеСтрокиРезультата(Результат, Ожидание);
ПроверитьЧетыреГруппыМесяцев(Результат, Ожидание);
Если Источник.Количество() <> 3 Тогда
ВызватьИсключение "Собственный источник изменился во время обхода";
КонецЕсли;
Исключение
Менеджер.Закрыть();
ВызватьИсключение;
КонецПопытки;
Менеджер.Закрыть();
КонецПроцедуры
Функция СоздатьСвойИсточникДат()
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата"));
Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(4, 0, ДопустимыйЗнак.Неотрицательный)));
Возврат Таблица;
КонецФункции
Процедура ПроверитьСвоюВходнуюСтроку(ДатаСтроки, Количество)
Если ТипЗнч(ДатаСтроки) <> Тип("Дата") Тогда
ВызватьИсключение "Дата собственной строки должна иметь тип Дата";
КонецЕсли;
Если ДатаСтроки < Дата(2026, 1, 1) Или ДатаСтроки > Дата(2026, 4, 1) Тогда
ВызватьИсключение "Собственный ввод ограничен 01.01.2026 00:00:00..01.04.2026 00:00:00";
КонецЕсли;
Если ТипЗнч(Количество) <> Тип("Число") Тогда
ВызватьИсключение "Количество собственной строки должно иметь тип Число";
КонецЕсли;
Если Количество < 0 Или Количество > 9999 Или Количество <> Цел(Количество) Тогда
ВызватьИсключение "Собственное количество должно быть целым от 0 до 9999";
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьСвоюСтрокуДаты(Таблица, ДатаСтроки, Количество)
ПроверитьСвоюВходнуюСтроку(ДатаСтроки, Количество);
СтрокаИсточника = Таблица.Добавить();
СтрокаИсточника.Дата = ДатаСтроки;
СтрокаИсточника.Количество = Количество;
КонецПроцедуры
Процедура ПроверитьОтклонениеСвоегоВвода(ДатаСтроки, Количество)
ОшибкаПолучена = Ложь;
Попытка
ПроверитьСвоюВходнуюСтроку(ДатаСтроки, Количество);
Исключение
ОшибкаПолучена = Истина;
Сообщить("Ручной опыт: собственный неверный ввод отклонён. " + ОписаниеОшибки());
КонецПопытки;
Если Не ОшибкаПолучена Тогда
ВызватьИсключение "Ожидалось отклонение конкретного собственного неверного ввода";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьДатуРезультата(Факт, Ожидание)
Если ТипЗнч(Факт) <> Тип("Дата") Тогда
ВызватьИсключение "В результате ожидалась Дата, не Null и не строка";
КонецЕсли;
Если Факт <> Ожидание Тогда
ВызватьИсключение "Дата результата не совпала с собственным ожиданием";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьЧислоРезультата(Факт, Ожидание)
Если ТипЗнч(Факт) <> Тип("Число") Тогда
ВызватьИсключение "В результате ожидалось Число, не Null и не строка";
КонецЕсли;
Если Факт <> Ожидание Тогда
ВызватьИсключение "Число результата не совпало с собственным ожиданием";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьВидСтроки(Выборка, ОжидаемыйВид, ОжидаемаяГруппировка)
Вид = Выборка.ТипЗаписи();
ИмяГруппировки = Выборка.Группировка();
Если ТипЗнч(Вид) <> Тип("ТипЗаписиЗапроса") Или ТипЗнч(ИмяГруппировки) <> Тип("Строка") Тогда
ВызватьИсключение "Не совпал тип сведений о текущей строке выборки";
КонецЕсли;
Если Вид <> ОжидаемыйВид Или ИмяГруппировки <> ОжидаемаяГруппировка Тогда
ВызватьИсключение "Уровень итога перепутан с детальной строкой результата";
КонецЕсли;
КонецПроцедуры
Функция НайтиСвоёОжиданиеМесяца(Ожидание, Период)
Если ТипЗнч(Период) <> Тип("Дата") Тогда
ВызватьИсключение "Ключ месяца результата должен иметь тип Дата";
КонецЕсли;
Для Каждого Месяц Из Ожидание Цикл
Если Месяц.Период = Период Тогда
Возврат Месяц;
КонецЕсли;
КонецЦикла;
ВызватьИсключение "В результате появился месяц вне четырёх собственных ожиданий";
КонецФункции
Процедура ПроверитьНовуюДату(УжеНайденные, Период)
Если УжеНайденные.Найти(Период) <> Неопределено Тогда
ВызватьИсключение "В результате повторился собственный месячный ключ";
КонецЕсли;
УжеНайденные.Добавить(Период);
КонецПроцедуры
Процедура ПоказатьФактическийСыройРесурс(Период, Значение)
ФактическийТип = ТипЗнч(Значение);
Если ФактическийТип = Тип("Null") Тогда
ТекстЗначения = "Null";
Иначе
ТекстЗначения = Строка(Значение);
КонецЕсли;
Сообщить("Месяц " + Строка(Период) + ": сырой ресурс=" + ТекстЗначения + "; фактический тип=" + Строка(ФактическийТип));
КонецПроцедуры
Процедура ПроверитьДвеИсходныеСтрокиРезультата(Результат, Ожидание)
Если Результат.Колонки.Количество() <> 2 Тогда
ВызватьИсключение "В собственном результате должны быть только Период и Количество";
КонецЕсли;
Детали = Результат.Выбрать(ОбходРезультатаЗапроса.Прямой, "");
Найденные = Новый Массив;
СуммаДеталей = 0;
Пока Детали.Следующий() Цикл
ПроверитьВидСтроки(Детали, ТипЗаписиЗапроса.ДетальнаяЗапись, "");
ОжидаемыйМесяц = НайтиСвоёОжиданиеМесяца(Ожидание, Детали.Период);
Если ОжидаемыйМесяц.КоличествоДеталей <> 1 Тогда
ВызватьИсключение "Дополненный пустой месяц ошибочно появился среди деталей";
КонецЕсли;
ПроверитьНовуюДату(Найденные, Детали.Период);
ПроверитьДатуРезультата(Детали.Период, ОжидаемыйМесяц.Период);
ПроверитьЧислоРезультата(Детали.Количество, ОжидаемыйМесяц.СуммаДеталей);
СуммаДеталей = СуммаДеталей + Детали.Количество;
КонецЦикла;
Если Найденные.Количество() <> 2 Или СуммаДеталей <> 9 Тогда
ВызватьИсключение "Полный состав двух детальных строк результата не совпал";
КонецЕсли;
Сообщить("Полный состав деталей: январь/5 и март/4; типы Дата/Число, сумма 9");
КонецПроцедуры
Процедура ПроверитьЧетыреГруппыМесяцев(Результат, Ожидание)
Месяцы = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Период", "Все");
Найденные = Новый Массив;
ВсегоДеталей = 0;
ВсегоПоСвоемуПравилу = 0;
Пока Месяцы.Следующий() Цикл
ПроверитьВидСтроки(Месяцы, ТипЗаписиЗапроса.ИтогПоГруппировке, "Период");
ОжидаемыйМесяц = НайтиСвоёОжиданиеМесяца(Ожидание, Месяцы.Период);
ПроверитьНовуюДату(Найденные, Месяцы.Период);
ПроверитьДатуРезультата(Месяцы.Период, ОжидаемыйМесяц.Период);
ПоказатьФактическийСыройРесурс(Месяцы.Период, Месяцы.Количество);
Если ОжидаемыйМесяц.КоличествоДеталей = 1 Тогда
ПроверитьЧислоРезультата(Месяцы.Количество, ОжидаемыйМесяц.СуммаДеталей);
КонецЕсли;
ДеталиМесяца = Месяцы.Выбрать(ОбходРезультатаЗапроса.Прямой, "");
КоличествоДеталей = 0;
СуммаДеталейМесяца = 0;
Пока ДеталиМесяца.Следующий() Цикл
ПроверитьВидСтроки(ДеталиМесяца, ТипЗаписиЗапроса.ДетальнаяЗапись, "");
ПроверитьДатуРезультата(ДеталиМесяца.Период, ОжидаемыйМесяц.Период);
ПроверитьЧислоРезультата(ДеталиМесяца.Количество, ОжидаемыйМесяц.СуммаДеталей);
КоличествоДеталей = КоличествоДеталей + 1;
СуммаДеталейМесяца = СуммаДеталейМесяца + ДеталиМесяца.Количество;
КонецЦикла;
ПроверитьЧислоРезультата(КоличествоДеталей, ОжидаемыйМесяц.КоличествоДеталей);
ПроверитьЧислоРезультата(СуммаДеталейМесяца, ОжидаемыйМесяц.СуммаДеталей);
ВсегоДеталей = ВсегоДеталей + КоличествоДеталей;
ВсегоПоСвоемуПравилу = ВсегоПоСвоемуПравилу + СуммаДеталейМесяца;
Сообщить("Собственное правило BSL: месяц=" + Строка(Месяцы.Период) + "; деталей=" + Строка(КоличествоДеталей) + "; сумма деталей=" + Строка(СуммаДеталейМесяца));
КонецЦикла;
Если Найденные.Количество() <> 4 Или ВсегоДеталей <> 2 Или ВсегоПоСвоемуПравилу <> 9 Тогда
ВызватьИсключение "Полный состав четырёх месячных итогов и двух вложенных деталей не совпал";
КонецЕсли;
Сообщить("Четыре месяца проверены независимо от порядка: 5/0/4/0 по собственному правилу BSL");
КонецПроцедурыРазбор по шагам
Весь код — один серверный общий модуль с экспортной процедурой запуска и всеми указанными помощниками; ни один помощник не получает неизвестные данные извне.
Типизированный источник имеет два столбца: Дата с единственным типом Дата и Количество с единственным типом Число(4,0), неотрицательное. Данные полностью заданы: 15.01.2026/2,20.01.2026/3,07.03.2026/4.
Собственная проверка допускает даты от 01.01.2026 00:00:00 до 01.04.2026 00:00:00 включительно, целое количество 0..9999. Это наши ограничения входа, не дополнительные свойства оператора ПЕРИОДАМИ.
Сначала отдельно проверить обе границы и девять неверных входов, не добавляя их в таблицу. Локальная Попытка охватывает только собственный валидатор: отсутствующая дата/количество, строки вместо даты/числа, выход за границы, отрицательное, слишком большое и дробное количество.
Поместить только три корректные строки во ВТСобственныеДаты собственного менеджера. Подготовительный запрос не объединяет, не соединяет и не группирует внешний ТаблицаЗначений; группировка выполняется уже над своей временной таблицей.
НАЧАЛОПЕРИОДА(Дата,МЕСЯЦ) переводит январские даты к 01.01.2026, мартовскую к 01.03.2026. СГРУППИРОВАТЬ ПО даёт две обычные строки результата с количествами 5 и 4.
ИТОГИ СУММА(Количество) ПО Период ПЕРИОДАМИ(...01.01.2026,01.04.2026) добавляет месячные итоговые записи. Поле контрольной точки имеет тип Дата. Обе границы намеренно начала месяцев, как в установленном нативном примере, который включает последний указанный месяц.
Прямой обход с явно пустым списком группировок выбирает детали: только январь/5 и март/4. Каждая имеет ТипЗаписи ДетальнаяЗапись и пустое имя группировки; здесь деталь означает строку результата после GROUP BY, не одну из трёх строк источника.
Групповой обход использует имя Период и третий аргумент Все. Страница date_complitions прямо требует все записи измерения для показанного дополнения, а нативные Выбрать обоих объектов описывают значение Все. Преждевременное чтение до Следующий исключено.
Каждый из четырёх месяцев должен иметь тип Дата, точное значение 01.01/01.02/01.03/01.04.2026, ТипЗаписи ИтогПоГруппировке и имя Период. Повторы и неизвестные месяцы отклоняются; сопоставление не зависит от порядка обхода.
В каждом месячном итоге показать фактическое Количество и ТипЗнч. У января и марта отдельно строго проверить числа 5 и 4. У февраля и апреля не приписывать заранее ни ноль, ни Null: справка СУММА не задаёт для нашего ресурса самостоятельный контракт синтетического пустого месяца.
Выбрать вложенные детали текущего месяца прямым обходом с пустой группировкой. Январь содержит ровно январь/5, март ровно март/4; февраль и апрель не содержат деталей. Проверить оба поля каждой существующей детали и её тип записи.
СуммаДеталейМесяца начинается с собственного числового 0 и увеличивается только прочитанными количествами деталей. Поэтому наш показатель BSL равен 5,0,4,0 — это явно заданное правило отображения, а не утверждение о сыром СУММА у дополненного итога.
Проверить полный состав: четыре разных месячных ключа, две вложенные детали, сумма деталей 9. Не складывать одновременно итоговые записи и детали; такое удвоение дало бы неверные 18.
Закрыть только собственный менеджер при успехе и исключении. Ошибки подготовки, нормального запроса и проверок не маскируются под ожидаемые: внешняя Попытка закрывает менеджер и повторно возбуждает исключение.
Как проверить результат
Прямой результат содержит ровно два поля Период/Количество и две строки (01.01.2026,5),(01.03.2026,4), с типами Дата/Число без Null.
Полный набор групп: январь,февраль,март,апрель 2026; вид ИтогПоГруппировке, имя Период. Количество деталей по месяцам равно 1,0,1,0, а все существующие детали полностью проверены.
Январский и мартовский сырые ресурсы строго равны числам 5/4. Для двух пустых месяцев будущий ручной запуск выводит фактические сырые значения и их типы, не заранее обещанный ноль или Null.
Отдельный собственный показатель BSL по деталям равен 5,0,4,0 и даёт общую сумму 9. Он не использует неизвестный сырой ресурс пустой группы.
Две положительные границы проходят собственную проверку; девять отрицательных опытов ожидаемо отклоняются в будущем ручном запуске и не добавляют строк источника. Три исходные строки остаются неизменными.
Ожидаемый результат
Воспроизводимый опыт дополнения диапазона месяцев показывает реальные месячные итоги, отсутствие деталей у добавленных периодов и честную границу знания о сыром пустом ресурсе; все ожидаемые записи проверены независимо от порядка.
На что обратить внимание
ПЕРИОДАМИ относится к итогам по датированной контрольной точке. Он не вставляет новые исходные строки и не даёт право считать месячный итог дополнительной продажей.
Если начальная или конечная дата не указаны, native использует первую и последнюю дату в результате. Здесь обе заданы явно: мы не обещаем появление апреля при отсутствии конечной границы.
Для произвольного времени внутри дня, иных видов периода или обратного диапазона этот модуль не заявляет непроверенную семантику границ. Изменение условий требует отдельного опыта и полного нового ожидания.
Нативный пример дополнения показывает нули для суммы количества покупок, полученного через КОЛИЧЕСТВО(Ссылка). Это не использовано как доказательство универсального нуля СУММА произвольного ресурса пустого периода.
Фактическое сырое значение пустого ресурса сохраняется в диагностике и проверяется по типу лишь как наблюдение. Для заданного показателя отчёта ноль получается нашим явно написанным накоплением деталей в BSL.
Третий аргумент Все задаёт источник значений группировки, не сортировку. Проверка полного состава не обещает порядок месячных итогов без отдельного доказанного контракта.
СГРУППИРОВАНОПО — функция группирующих наборов GROUP BY по отдельному нативному контракту, а не синоним ТипЗаписи или ИТОГИ. Этот опыт не прикрепляется к странице GROUPING.
Python-проверки моделируют только собственные входные данные, месячные ключи и показатель по деталям, а также сверяют установленную справку. Они не исполняют ПЕРИОДАМИ, обход выборки или СУММА внутри 1С.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.