Имя: Пароль:
1C
1С v8
Сдвиг даты с учетом производственного календаря
0 apd123
 
04.10.14
00:29
Понадобилось сделать функцию, которая вычисляет дату, отстоящую от начальной на заданное количество рабочих дней, с учетом производственного календаря, т.е. с учетом праздников и переносов выходных. Как ни странно, готового решения найти не удалось. Точнее, для типовых конфигураций, содержащих регламентированный производственный календарь вот тут v8: v8: Как к дате прибавить n дней исключая праздники? есть монструозная функция, но у меня довольно простая нетленка, поэтому прикручивать всю эту конструкцию не было смысла.

Итак, для начала понадобится собственно производственный календарь. Им будет обычный регистр сведений "Календарь" с одним измерением "Дата" и одним ресурсом "ТипДня", который является ссылкой на перечисление "ТипДняКалендаря", содержащее три значения: Рабочий, Выходной и Предпразничный. Последнее для вычисления смещения даты не понадобится, но может пригодиться в будущем для других целей.

Заполняем календарь вот так

Процедура ЗаполнитьКалендарьНаСервере()
    НаборЗаписей = РегистрыСведений.Календарь.СоздатьНаборЗаписей();
    НаборЗаписей.Записать();
        
    Для ТГод = 2009 по 2020 Цикл
        Для ТМесяц = 1 по 12 Цикл
            Для ТДень = 1 по 31 Цикл                
                Попытка            
                    ТекущаяДата = Дата(ТГод,ТМесяц,ТДень);    
                Исключение
                    Продолжить;
                КонецПопытки;            
            
                НовыйДень = РегистрыСведений.Календарь.СоздатьМенеджерЗаписи();
                НовыйДень.Дата = ТекущаяДата;
                Если ДеньНедели(ТекущаяДата) = 6 или ДеньНедели(ТекущаяДата) = 7 тогда
                    НовыйДень.ТипДня = Перечисления.ТипДняКалендаря.Выходной;
                Иначе
                    НовыйДень.ТипДня = Перечисления.ТипДняКалендаря.Рабочий;
                КонецЕсли;
                НовыйДень.Записать();
            КонецЦикла;
        КонецЦикла;
    КонецЦикла;
КонецПроцедуры

Годы, естественно, нужно подставить свои.

После этого проходим руками по календарю и руками проставляем праздники, предпразничные дни и переносы выходных. Можно и не руками, я сделал импорт из экселя, показалось что так будет быстрее. Нужные даты можно взять например тут http://buh.ru/calendar/2015/

И сама функция, вычисляющая дату со сдвигом

Функция РабДень(НачДача, Сдвиг) Экспорт
    Если Сдвиг >= 0 Тогда    
        Сдвиг         = Сдвиг + 1;
        Сортировка    = "ВОЗР";
        Отношение    = ">=";
    Иначе
        Сдвиг        = -Сдвиг;
        Сортировка    = "УБЫВ";
        Отношение    = "<";
    КонецЕсли;
    Запрос = Новый Запрос("
    |    ВЫБРАТЬ ПЕРВЫЕ " + Сдвиг + " Дата
    |   ИЗ РегистрСведений.Календарь
    |   ГДЕ Дата " + Отношение + " &ПервыйДень И ТипДня <> &Выходные    
    |    УПОРЯДОЧИТЬ ПО Дата " + Сортировка);
    
    Запрос.УстановитьПараметр("ПервыйДень", НачДача);
    Запрос.УстановитьПараметр("Выходные", Перечисления.ТипДняКалендаря.Выходной);
    Результат = Запрос.Выполнить().Выгрузить();
    Возврат Результат.Получить(Результат.Количество()-1).Дата;
КонецФункции
1 Fragster
 
гуру
04.10.14
00:34
и что не работает?
2 apd123
 
04.10.14
00:37
(1) Работает. Делюсь для тех кто как я потратил день на поиски готового решения не в силах поверить что его нет.
3 France
 
04.10.14
00:38
Ожидает функциональности "монструозной" типовой.. сам делать не хочет - ожидает, что мистяне сделают
4 apd123
 
04.10.14
00:41
(3) Так ведь не монструозности, а необходимого минимума. И таки да, я удивлен что такой нужной штуки не нашлось.
5 France
 
04.10.14
00:53
(4) ну, в своих поделках я пользовал типовую.. ибо поделка сама была типовой))а та?, реально - создалось ощущение, что есть вопрс))на мисте секретами через кз делились)) зы.. или еще делятся?((
6 apd123
 
04.10.14
01:02
(5) Ох, да я тут новенький, про КЗ и не подумал. Скопипастил туда.
В любом случае тут принимается критика, советы и т.п.
7 Wobland
 
04.10.14
02:18
(6) функция поломается при работе с датой, которой нет в календаре
8 Wobland
 
04.10.14
02:19
+(7) Результат.Получить(-1)
9 apd123
 
06.10.14
11:15
(7) Я думал над этим и пришел к выводу что она и должна ломаться, поскольку непонятно что нужно отдавать в таких случаях.

(8) При нулевом сдвиге отрабатывает как нужно.
Пользователь не знает, чего он хочет, пока не увидит то, что он получил. Эдвард Йодан