Сдвиг даты с учетом производственного календаряВычисление даты, отстоящей от начальной на заданное количество рабочих дней, с учетом производственного календаря, т.е. с учетом праздников и переносов выходных. | | Автор статьи: 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).Дата;
КонецФункции |