| Сдвиг даты с учетом производственного календаря| Вычисление даты, отстоящей от начальной на заданное количество рабочих дней, с учетом производственного календаря, т.е. с учетом праздников и переносов выходных. |  | Автор статьи: apd123 | Редакторы: Последняя редакция №2 от 04.10.14 | История
 URL: http://kb.mista.ru/article.php?id=933
 |  | 
 Ключевые слова: сдвиг даты, производственный календарь, праздники, выходные
 
 
 Понадобилось сделать функцию, которая вычисляет дату, отстоящую от начальной на заданное количество рабочих дней, с
 учетом
 производственного календаря, т.е. с учетом праздников и переносов выходных. Как ни странно, готового решения найти не
 удалось. Точнее,
 для типовых конфигураций, содержащих регламентированный производственный календарь вот тут
 v8: v8: Как к дате прибавить n дней исключая праздники? есть монструозная функция, но у меня довольно простая нетленка, поэтому
 прикручивать всю эту конструкцию не было смысла.
 
 Итак, для начала понадобится собственно производственный календарь. Им будет обычный регистр сведений "Календарь" с
 одним измерением
 "Дата" и одним ресурсом "ТипДня", который является ссылкой на перечисление "ТипДняКалендаря", содержащее три
 значения: Рабочий,
 Выходной и Предпразничный. Последнее для вычисления смещения даты не понадобится, но может пригодиться в будущем
 для других целей.
 
 Заполняем календарь вот так
 
 
 Процедура ЗаполнитьКалендарьНаСервере()
НаборЗаписей = РегистрыСведений.Календарь.СоздатьНаборЗаписей();
 НаборЗаписей.Записать();
 
 Для ТГод = 2009 по 2020 Цикл
 Для ТМесяц = 1 по 12 Цикл
 Для ТДень = 1 по 31 Цикл
 Попытка
 ТекущаяДата = Дата(ТГод,ТМесяц,ТДень);
 Исключение
 Продолжить;
 КонецПопытки;
 
 НовыйДень = РегистрыСведений.Календарь.СоздатьМенеджерЗаписи();
 НовыйДень.Дата = ТекущаяДата;
 Если ДеньНедели(ТекущаяДата) = 6 или ДеньНедели(ТекущаяДата) = 7 тогда
 НовыйДень.ТипДня = Перечисления.ТипДняКалендаря.Выходной;
 Иначе
 НовыйДень.ТипДня = Перечисления.ТипДняКалендаря.Рабочий;
 КонецЕсли;
 НовыйДень.Записать();
 КонецЦикла;
 КонецЦикла;
 КонецЦикла;
 КонецПроцедуры
 
 Годы, естественно, нужно подставить свои.
 
 После этого проходим руками по календарю и руками проставляем праздники, предпразничные дни и переносы выходных.
 Можно и не
 руками, я сделал импорт из экселя, показалось что так будет быстрее. Нужные даты можно взять например тут
 http://buh.ru/calendar/2015/
 
 И сама функция, вычисляющая дату со сдвигом
 
 Функция РабДень(НачДача, Сдвиг) Экспорт
Если Сдвиг >= 0 Тогда
 Сдвиг         = Сдвиг + 1;
 Сортировка    = "ВОЗР";
 Отношение    = ">=";
 Иначе
 Сдвиг        = -Сдвиг;
 Сортировка    = "УБЫВ";
 Отношение    = "";
 КонецЕсли;
 Запрос = Новый Запрос("
 |    ВЫБРАТЬ ПЕРВЫЕ " + Сдвиг + " Дата
 |   ИЗ РегистрСведений.Календарь
 |   ГДЕ Дата " + Отношение + " &ПервыйДень И ТипДня <> &Выходные
 |    УПОРЯДОЧИТЬ ПО Дата " + Сортировка);
 
 Запрос.УстановитьПараметр("ПервыйДень", НачДача);
 Запрос.УстановитьПараметр("Выходные", Перечисления.ТипДняКалендаря.Выходной);
 Результат = Запрос.Выполнить().Выгрузить();
 Возврат Результат.Получить(Результат.Количество()-1).Дата;
 КонецФункции
 |