// кэш для хранения параметров праздников
// храним номер месяца в году и номер дня в месяце
Праздники = Новый ТаблицаЗначений;
Праздники.Колонки.Добавить("Месяц");
Праздники.Колонки.Добавить("День");
// вначале количество рабочих дней полагаем равным общему числу дней в году
// потом вычитаем выходные и праздники
РабочихДней = ДеньГода(Дата(Год(ТекущийГод),Месяц(КонецГода(ТекущийГод)),День(КонецГода(ТекущийГод)))) -
ДеньГода(Дата(Год(ТекущийГод),Месяц(ТекущийГод),День(ТекущийГод))) + 1;
// дни и признак праздничного месяца
Отбор.Вставить("Месяц",Месяц(ТекущийМесяц));
ДниПраздников = ПраздничныеДниМесяца(Праздники,Отбор);
ЭтоПраздничныйМесяц = ДниПраздников.Количество();
// посчитаем субботы, воскресенья каждого месяца
ВоскресеньеМесяца = ТекущийМесяц + (ДнейВНеделе - ДеньНедели(ТекущийМесяц)) * СекундВДне;
СубботаМесяца = ВоскресеньеМесяца - СекундВДне;
Пока Месяц(ВоскресеньеМесяца) = Месяц(ТекущийМесяц) Цикл
РабочихДней = РабочихДней - 1;
Если Месяц(СубботаМесяца) = Месяц(ТекущийМесяц) Тогда
РабочихДней = РабочихДней - 1;
КонецЕсли;
Если Месяц(СубботаМесяца) = Месяц(ТекущийМесяц) Тогда
РабочихДней = РабочихДней - 1;
КонецЕсли;
// разберемся с праздниками
Если ЭтоПраздничныйМесяц Тогда
Для каждого Праздник Из ДниПраздников Цикл
// праздник не приходится на выходные
Если ДеньНедели(Дата(Год(ТекущийМесяц),Праздник.Месяц,Праздник.День)) < ДнейВНеделе - 1 Тогда
РабочихДней = РабочихДней - 1;
КонецЕсли;
КонецЦикла;
КонецЕсли;
// наращиваем месяц
ТекущийМесяц = ДобавитьМесяц(ТекущийМесяц,1);
КонецЦикла;
Сообщить("В " + Год(ТекущийГод) + "-м году " + РабочихДней + " рабочих дней.",СтатусСообщения.Информация);
// наращиваем год
ТекущийГод = ТекущийМесяц;
КонецЦикла;
КонецПроцедуры
Результат:
В 2 022-м году 258 рабочих дней.
В 2 021-м году 258 рабочих дней.
В 2 020-м году 261 рабочих дней.
В 2 019-м году 259 рабочих дней.
В 2 018-м году 258 рабочих дней.
В 2 017-м году 258 рабочих дней.
В 2 016-м году 258 рабочих дней.
В 2 015-м году 259 рабочих дней.
В 2 014-м году 260 рабочих дней.
В 2 013-м году 259 рабочих дней.
В 2 012-м году 259 рабочих дней.
Пока ДатаОтсчета < КонецКалендаря Цикл
ТекущийГод = Год(ДатаОтсчета);
ДеньНед = ДеньНедели(ДатаОтсчета);
Если (ДеньНед >= 6) ИЛИ (ДатаОтсчета = Дата(Год(ДатаОтсчета),1,1) ИЛИ ДатаОтсчета = Дата(Год(ДатаОтсчета),2,23) ИЛИ ДатаОтсчета=Дата(Год(ДатаОтсчета),5,8)) Тогда
ДатаОтсчета = ДатаОтсчета + ОдинДень ;
Продолжить;
КонецЕсли;
Если ТекущийГод=ПрошлыйГод Тогда
КоличествоРабочихДней = КоличествоРабочихДней + 1;
РабочиеДниВГоду.Вставить(СчетчикЛет,КоличествоРабочихДней);
ИначеЕсли ТекущийГод > ПрошлыйГод Тогда
Сообщить ("В "+ Формат(ПрошлыйГод,"ЧГ=0") + " году рабочих дней: " + КоличествоРабочихДней);
ПрошлыйГод=ТекущийГод;
СчетчикЛет=СчетчикЛет + 1;
КоличествоРабочихДней = 1;
РабочиеДниВГоду.Добавить();
РабочиеДниВГоду.Вставить(СчетчикЛет,КоличествоРабочихДней);
КонецЕсли;
РабочихДней = 0;
Для СчетчикМесяцев = 1 По 12 Цикл
КонецМесяца = День(КонецМесяца(Дата(СчетчикЛет, СчетчикМесяцев,01)));
Для СчетчкДней = 1 По КонецМесяца Цикл
ТекДата =Дата(СчетчикЛет, СчетчикМесяцев, СчетчкДней);
ТекДеньНедели = ДеньНедели(ТекДата);
Если (ТекДеньНедели <> 6 И ТекДеньНедели <> 7) И Праздники.Найти(ТекДата) = Неопределено Тогда
РабочихДней = РабочихДней + 1;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = Строка(СчетчикЛет) + " год - " + РабочихДней + " рабочих дней";
Сообщение.Сообщить();
КонецЦикла;
Все материалы этого сайта являются составной частью Базового / Продвинутого курсов по программированию - и являются объектами авторского и имущественного права.
Любое их распространение без письменного согласования с авторами запрещено.
Функция СекундВДне()
Возврат 60 * 60 * 24;
КонецФункции // ПоменятьМестамиПараметры()
&НаСервереБезКонтекста
Функция МесяцевВГоду()
Возврат 12;
КонецФункции // МесяцевВГоду()
&НаСервереБезКонтекста
Функция ДнейВНеделе()
Возврат 7;
КонецФункции
&НаСервереБезКонтекста
Функция ПраздничныеДниМесяца(Праздники,Отбор)
Возврат Праздники.НайтиСтроки(Отбор);
КонецФункции // МесяцевВГоду()
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// кэш для хранения параметров праздников
// храним номер месяца в году и номер дня в месяце
Праздники = Новый ТаблицаЗначений;
Праздники.Колонки.Добавить("Месяц");
Праздники.Колонки.Добавить("День");
Строка = Праздники.Добавить();
Строка.Месяц = 1;
Строка.День = 1;
Строка = Праздники.Добавить();
Строка.Месяц = 2;
Строка.День = 23;
Строка = Праздники.Добавить();
Строка.Месяц = 3;
Строка.День = 8;
ЛетАнализа = 10;
МесяцевВГоду = МесяцевВГоду();
ДнейВНеделе = ДнейВНеделе();
Отбор = Новый Структура;
НачальныйГод = НачалоГода(ТекущаяДата());
КонечныйГод = ДобавитьМесяц(НачалоГода(ТекущаяДата()),МесяцевВГоду * ЛетАнализа);
ТекущийГод = НачальныйГод;
СекундВДне = СекундВДне();
Пока ТекущийГод <= КонечныйГод Цикл
// вначале количество рабочих дней полагаем равным общему числу дней в году
// потом вычитаем выходные и праздники
РабочихДней = ДеньГода(Дата(Год(ТекущийГод),Месяц(КонецГода(ТекущийГод)),День(КонецГода(ТекущийГод)))) -
ДеньГода(Дата(Год(ТекущийГод),Месяц(ТекущийГод),День(ТекущийГод))) + 1;
ТекущийМесяц = ТекущийГод;
ПоследнийМесяц = НачалоМесяца(КонецГода(ТекущийГод));
Пока ТекущийМесяц <= ПоследнийМесяц Цикл
// дни и признак праздничного месяца
Отбор.Вставить("Месяц",Месяц(ТекущийМесяц));
ДниПраздников = ПраздничныеДниМесяца(Праздники,Отбор);
ЭтоПраздничныйМесяц = ДниПраздников.Количество();
// посчитаем субботы, воскресенья каждого месяца
ВоскресеньеМесяца = ТекущийМесяц + (ДнейВНеделе - ДеньНедели(ТекущийМесяц)) * СекундВДне;
СубботаМесяца = ВоскресеньеМесяца - СекундВДне;
Пока Месяц(ВоскресеньеМесяца) = Месяц(ТекущийМесяц) Цикл
РабочихДней = РабочихДней - 1;
Если Месяц(СубботаМесяца) = Месяц(ТекущийМесяц) Тогда
РабочихДней = РабочихДней - 1;
КонецЕсли;
ВоскресеньеМесяца = ВоскресеньеМесяца + ДнейВНеделе * СекундВДне;
СубботаМесяца = СубботаМесяца + ДнейВНеделе * СекундВДне;
КонецЦикла;
Если Месяц(СубботаМесяца) = Месяц(ТекущийМесяц) Тогда
РабочихДней = РабочихДней - 1;
КонецЕсли;
// разберемся с праздниками
Если ЭтоПраздничныйМесяц Тогда
Для каждого Праздник Из ДниПраздников Цикл
// праздник не приходится на выходные
Если ДеньНедели(Дата(Год(ТекущийМесяц),Праздник.Месяц,Праздник.День)) < ДнейВНеделе - 1 Тогда
РабочихДней = РабочихДней - 1;
КонецЕсли;
КонецЦикла;
КонецЕсли;
// наращиваем месяц
ТекущийМесяц = ДобавитьМесяц(ТекущийМесяц,1);
КонецЦикла;
Сообщить("В " + Год(ТекущийГод) + "-м году " + РабочихДней + " рабочих дней.",СтатусСообщения.Информация);
// наращиваем год
ТекущийГод = ТекущийМесяц;
КонецЦикла;
КонецПроцедуры
Результат:
В 2 022-м году 258 рабочих дней.
В 2 021-м году 258 рабочих дней.
В 2 020-м году 261 рабочих дней.
В 2 019-м году 259 рабочих дней.
В 2 018-м году 258 рабочих дней.
В 2 017-м году 258 рабочих дней.
В 2 016-м году 258 рабочих дней.
В 2 015-м году 259 рабочих дней.
В 2 014-м году 260 рабочих дней.
В 2 013-м году 259 рабочих дней.
В 2 012-м году 259 рабочих дней.
Юрий, принято.
Процедура ИсполнитьВолю()
КонецКалендаря = ТекущаяДата()+(60*60*24*365*10);
ОдинДень = 60*60*24;
ДатаОтсчета= ТекущаяДата();
КоличествоРабочихДней = 0;
ТекущийГод = Год(ДатаОтсчета);
ПрошлыйГод = ТекущийГод;
РабочиеДниВГоду = Новый Массив;
РабочиеДниВГоду.Добавить();
СчетчикЛет = 0;
Пока ДатаОтсчета < КонецКалендаря Цикл
ТекущийГод = Год(ДатаОтсчета);
ДеньНед = ДеньНедели(ДатаОтсчета);
Если (ДеньНед >= 6) ИЛИ (ДатаОтсчета = Дата(Год(ДатаОтсчета),1,1) ИЛИ ДатаОтсчета = Дата(Год(ДатаОтсчета),2,23) ИЛИ ДатаОтсчета=Дата(Год(ДатаОтсчета),5,8)) Тогда
ДатаОтсчета = ДатаОтсчета + ОдинДень ;
Продолжить;
КонецЕсли;
Если ТекущийГод=ПрошлыйГод Тогда
КоличествоРабочихДней = КоличествоРабочихДней + 1;
РабочиеДниВГоду.Вставить(СчетчикЛет,КоличествоРабочихДней);
ИначеЕсли ТекущийГод > ПрошлыйГод Тогда
Сообщить ("В "+ Формат(ПрошлыйГод,"ЧГ=0") + " году рабочих дней: " + КоличествоРабочихДней);
ПрошлыйГод=ТекущийГод;
СчетчикЛет=СчетчикЛет + 1;
КоличествоРабочихДней = 1;
РабочиеДниВГоду.Добавить();
РабочиеДниВГоду.Вставить(СчетчикЛет,КоличествоРабочихДней);
КонецЕсли;
ДатаОтсчета = ДатаОтсчета + ОдинДень;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура Щелк(Команда)
ИсполнитьВолю();
КонецПроцедуры
idspooler, отчет принят.
Процедура ВычислитьКоличествоРабочихДней(Команда)
ГодНачалоОтсчета = Год(ТекущаяДата());
ГодОкончанияОтсчета = ГодНачалоОтсчета + 10;
Для СчетчикЛет = ГодНачалоОтсчета По ГодОкончанияОтсчета Цикл
Праздники = Новый Массив;
Праздники.Добавить(Дата(СчетчикЛет, 01, 01));
Праздники.Добавить(Дата(СчетчикЛет, 02, 23));
Праздники.Добавить(Дата(СчетчикЛет, 03, 08));
РабочихДней = 0;
Для СчетчикМесяцев = 1 По 12 Цикл
КонецМесяца = День(КонецМесяца(Дата(СчетчикЛет, СчетчикМесяцев,01)));
Для СчетчкДней = 1 По КонецМесяца Цикл
ТекДата =Дата(СчетчикЛет, СчетчикМесяцев, СчетчкДней);
ТекДеньНедели = ДеньНедели(ТекДата);
Если (ТекДеньНедели <> 6 И ТекДеньНедели <> 7) И Праздники.Найти(ТекДата) = Неопределено Тогда
РабочихДней = РабочихДней + 1;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = Строка(СчетчикЛет) + " год - " + РабочихДней + " рабочих дней";
Сообщение.Сообщить();
КонецЦикла;
КонецПроцедуры
Baggi-09, принято.