При разработке отчетов и обработок в 1С часто возникает задача получить список всех дней внутри заданного временного интервала. Разберем по шагам, как правильно организовать перебор дат в платформе 1С:Предприятие 7.7, рассмотрим тонкости работы циклов, обработку исключительных ситуаций и сравним этот подход с платформой 1С:Предприятие 8.
В платформе 1С 7.7 тип данных Дата поддерживает прямую работу в цикле Для ... По. Счетчик цикла автоматически увеличивается на один день на каждой итерации. Посмотрим на классический пример:
Для сч = НачДата По КонДата Цикл
Сообщить(сч);
КонецЦикла;
В данном фрагменте переменная сч последовательно принимает значение каждого дня в интервале от НачДата до КонДата включительно.
При использовании стандартного цикла важно помнить о следующих нюансах:
Для ... По работает исключительно в сторону увеличения с шагом в один день. Если значение переменной НачДата окажется больше значения КонДата, тело цикла не выполнится ни разу без генерации синтаксических ошибок.'00.00.0000'), цикл может повести себя некорректно. Рекомендуется предварительно проверять заполненность переменных.Проанализируем пример безопасной проверки входных параметров:
Если (ПустоеЗначение(НачДата) = 1) Или (ПустоеЗначение(КонДата) = 1) Тогда
Предупреждение("Укажите границы периода!");
Возврат;
КонецЕсли;
Если НачДата > КонДата Тогда
Предупреждение("Дата начала не может быть позже даты окончания!");
Возврат;
КонецЕсли;
Если перед нами стоит задача вывести дни в обратном порядке (от даты окончания к дате начала) или выполнять перебор с произвольным шагом, цикл Для не подойдет. В таких случаях используем цикл Пока.
Рассмотрим пример перебора от конца периода к началу:
ТекДата = КонДата;
Пока ТекДата >= НачДата Цикл
Сообщить(ТекДата);
ТекДата = ТекДата - 1;
КонецЦикла;
Операция вычитания единицы из даты в 1С 7.7 сдвигает значение ровно на один день назад.
Часто требуется не просто вывести даты, а исключить выходные дни. Для этого внутри тела цикла применяем встроенную функцию НомерДняНедели. Функция возвращает 6 для субботы и 7 для воскресенья.
Разберем пример вывода только рабочих дней:
Для ТекДата = НачДата По КонДата Цикл
ДеньНедели = НомерДняНедели(ТекДата);
Если (ДеньНедели <> 6) И (ДеньНедели <> 7) Тогда
Сообщить("Рабочий день: " + ТекДата);
КонецЕсли;
КонецЦикла;
Если аналогичную задачу требуется решить в 1С 8.x, необходимо учитывать принципиальные отличия платформы:
Для ... По поддерживает только числовые счетчики. Попытка передать дату в заголовок цикла вызовет ошибку времени выполнения.Дата в 1С 8 содержит время с точностью до секунды. Операция Дата + 1 увеличивает значение на одну секунду, а не на один день. Чтобы сместиться на сутки, нужно прибавить 86400 секунд (24 часа * 60 минут * 60 секунд).Посмотрим, как аналогичный перебор дат реализуется в 1С 8:
ТекДата = НачалоДня(НачДата);
Пока ТекДата <= НачалоДня(КонДата) Цикл
Сообщить(Формат(ТекДата, "ДФ=dd.MM.yyyy"));
ТекДата = ТекДата + 86400;
КонецЦикла;
Использование функций НачалоДня гарантирует точное сопоставление дат без учета времени суток, которое могло быть записано в реквизитах.