Базовый курс. Домашнее задание №3

Третье задание по 0-му блоку базового курса.

Для выполнения рекомендуется изучить следующие главы 0-го блока.
Глава 11. Программный код
Глава 12. Примитивные типы данных
Глава 13. Контекст исполнения кода
Глава 14. Объектная техника
Глава 15. Сервисные средства по написанию кода
Глава 16. Основные объекты конфигурации.
Глава 17. Виды учета.

К сожалению, у Вас недостаточно прав для просмотра этой записи. Если Вы еще не залогинены на сайте — залогиньтесь. Если Вы оплачивали курс, у Вас активирован токен доступа, Вы залогинены, но Вы видите эту запись — напишите нам на e-mail поддержки.

комментария 174 на “Базовый курс. Домашнее задание №3”

  1. kontovskiy 14.01.2011 в 23:14

    <code>
    &НаКлиенте
    Процедура Команда1(Команда)

    Для Год=2010 По 2019 Цикл

    КонецГода = Дата(Год,12,31);
    КолвоДнейВГоду = ДеньГода(КонецГода);
    ЦелыхНедель = Цел(КолвоДнейВгоду/7);
    НеобработаноДней = КолвоДнейВгоду%7;
    Январь01 = Дата(Год,1,1);
    Февраль23 = Дата(Год,2,23);
    Март08 = Дата(Год,3,8);

    РабочихДней = ЦелыхНедель*5;
    Для Сч=1 По НеобработаноДней Цикл

    ТекДень = Дата(Год, 1, Сч);
    Если ДеньНедели(ТекДень)>6 Тогда
    РабочихДней = РабочихДней+1;
    КонецЕсли;

    КонецЦикла;

    РабочихДней = РабочихДней – РабочийДень(Январь01)
    – РабочийДень(Февраль23) – РабочийДень(Март08);

    Сообщить(“”+Строка(Год)+” год – “+РабочихДней+” рабочих дней”);

    КонецЦикла;

    КонецПроцедуры

    &НаКлиенте
    Функция РабочийДень(День)

    Если ДеньНедели(День)<6 Тогда

    Возврат 1;
    Иначе
    Возврат 0;

    КонецЕсли;
    КонецФункции
    </code>

  2. stevelagory 07.12.2010 в 14:45

    Доброго времени, уважаемые коллеги!
    Начинаю выкладывать решения по всем задачам, в том числе и по данному блоку.
    Я пошел по другому пути чем мои коллеги (судя по комментариям, правда ответ преподавателя пока не смотрел). Считаю свой алгоритм одним из оптимальных и буду благодарен если вы укажете мне на мою ошибку.
    Суть в следующем – нам не надо пербирать дни, посмотрите внимательно на календарь перед собой – количество суббот и воскресений зависит от того, на какой день приходится 1е января и является ли год високосным. Количсетво суббот и воскресейний  мы можем вычислить для в зависимости от того, на какой день недели выпадает 1-е января. Далее, нам надо определить на какие дни падают праздники (каждый из указанных в задании) и, если они выпали на будний день, приплюсовываем их к количеству выходных.
    <code>
    Функция КоличествоРабочихДней( Год )

    ВисокосныйГод = НЕ( Год % 4 ) ;
    КоличествоДнейВГоду = 365 + ВисокосныйГод ;

    ДеньНедели1Января = ДеньНедели( Дата( Год, 1, 1 ) ) ;

    Если ДеньНедели1Января = 5 Тогда
    КоличествоСубботИВоскресений = 104 + ВисокосныйГод ;
    ИначеЕсли ДеньНедели1Января = 6 Тогда
    КоличествоСубботИВоскресений = 105 + ВисокосныйГод ;
    ИначеЕсли ДеньНедели1Января = 7 Тогда
    КоличествоСубботИВоскресений = 105 ;
    Иначе
    КоличествоСубботИВоскресений = 104 ;
    КонецЕсли ;

    КоличествоПраздников = ( ДеньНедели( Дата( Год, 1, 1 ) ) < 6 ) +
    ( ДеньНедели( Дата( Год, 2, 23 ) ) < 6 ) +
    ( ДеньНедели( Дата( Год, 3, 8 ) ) < 6 ) ;

    Сообщить( “Количество праздников ” + Год + ” = ” + КоличествоПраздников ) ;

    ВыходныеДни = Новый Структура() ;
    Ключ = “Год2010” ; // + Год ;
    ВыходныеДни.Вставить( Ключ, КоличествоСубботИВоскресений + КоличествоПраздников ) ;
    Сообщить( “Год” + Год + ” = ” + ВыходныеДни.Год2010 ) ;

    Возврат КоличествоДнейВГоду – КоличествоСубботИВоскресений – КоличествоПраздников ;

    КонецФункции // КоличествоРабочихДней()
    </code>
    Теперь ответы на вопросы обратной связи:
    1) Мне понравился раздел про развитие платфомы, классификацию ошибок и операторы и их приоритеты (в голове навел порядок)
    2) Мне не совсем понятно (даже до сих пор) – что такое тонкий клиент и в чем отличие от толстого в режиме управляемого прилоджения – как его себе представить????
    3) Может имеет смысл подробнее рассказать про виды клиентов и режимы запуска – запутанно все такие это немного – что при это устанавливается на сам клиент и в чем между ними различия рассказать более подробно.
    Заранее спасибо!

    • Доброго дня!

      Оптимальность алгоритмов для этой задачи это интересный вопрос.
      Один из слушателей показал, что алгоритм перебора работает быстрее алгоритмов без циклов.
      Возможно ваш алгоритм действительно самый быстрый, поскольку в нем количество вычислений минимально.
      Однако, чтобы на 100% ответить на этот вопрос нужно будет провести замеры. Можете сделать это самостоятельно (Отладчик – Замер производительности).

      По поводу тонкого клиента.
      Знаете как работает RDP (Подключение к удаленному рабочему столу) в Windows? Если коротко – то на компьютер передается лишь изображение экрана другой машины, а обратно передаются движения мыши и нажатые клавиши.
      Примерно также работает и тонкий клиент 1С.
      Технологии немного различаются. Тонкий клиент 1С это все-таки самостоятельное приложение, и может решать простенькие задачи, однако основную работу будет выполнять сервер, к которому тонкий клиент подключается.

      Режимы запуска описаны в бонусном материале (Формы. Новый взгляд).
      Если вопросы по ним еще останутся – задавайте в мастер-группу.

  3. Реализовал расчет рабочих дней прямым перебором дней года, с суммированием и исключением из суммирования выходных праздничных дней. так как праздничные дни не переносятся то условие исключения такое: проверяемый день не выходной и не праздник. Евгений, Ваше решение конечно более производительно
    <code>&НаСервере
    Процедура ВывестиКоличествоРабочихДнейЗаГод(ГодДляРасчета)

    МассивПраздников = Новый Массив;
    МассивПраздников.Добавить(Дата(ГодДляРасчета,1,1));
    МассивПраздников.Добавить(Дата(ГодДляРасчета,2,23));
    МассивПраздников.Добавить(Дата(ГодДляРасчета,3,8));

    КоличествоРабочихДней = 0;

    ДатаПеребора        = НачалоГода(Дата(ГодДляРасчета,1,1));
    КонецГодаРасчета    = КонецГода(Дата(ГодДляРасчета,1,1));

    Пока ДатаПеребора <= КонецГодаРасчета Цикл
    Если ДеньНедели(ДатаПеребора) < 6 И МассивПраздников.Найти(ДатаПеребора) = Неопределено Тогда
    КоличествоРабочихДней = КоличествоРабочихДней + 1;
    КонецЕсли;
    ДатаПеребора = ДатаПеребора + 60*60*24; // плюс 24 часа – следующая дата
    КонецЦикла;

    Сообщить(“Год: “+Формат(ГодДляРасчета, “ЧГ=”)+” Кол-во раб. дней = “+Строка(КоличествоРабочихДней));

    КонецПроцедуры</code>

  4. Выполнено, проблем не возникло

  5. Задачу решила перебором по годам/месяцам/дням и от кол-ва рабочих дней  в году (которые изначально равны кол-ву всех дней в году) отнимала дни, порядковый номер которых  >=6 и отдельно проверяла на дату (праздник/не праздник) и отнимала, в случае надобности.
    Пришлось повозиться со структурой – для меня это новое, а именно с определением ключа “Год2010” и т.д.  – неразрывный пробел, однако :)

    Обратная связь:
    1. Нового – много, но больше всего озадачило различие между присваиванием и сравнением.
    2. Были большие непонятки в терминологии, но благодаря бонусу “Формы.Новый взгляд” много чего стало на свои места
    3. Сложно пока сказать, поскольку трудности возникают при решении практических задач, а ответы на них Вы предоставляете регулярно.

  6. Сделал немного не по заданию, т.е. не на несколько лет, а по полю на форме.

    Процедура ВычислитьРабДни(Команда)
    Начало2010 = НачалоГода(Год);
    Конец2010 = КонецГода(Год);

    ВсегоДней = Окр((Конец2010 – Начало2010)/(60*60*24));

    Праздник0101 = 1;
    Праздник2302 = 31+23;

    Если ВсегоДней > 364 Тогда
    Праздник0803 = 31+29+8;
    Иначе
    Праздник0803 = 31+28+8;
    КонецЕсли;

    ТекДеньНедели = 0;
    РабДней = 0;

    Для Счетчик = 1 По ВсегоДней Цикл
    ТекДеньНедели = ТекДеньНедели + 1;

    Если ТекДеньНедели <> 6 И ТекДеньНедели <> 7 Тогда

    Если Счетчик <> Праздник0101 И Счетчик <> Праздник2302 И Счетчик <> Праздник0803 Тогда
    РабДней = РабДней + 1;
    КонецЕсли;

    ИначеЕсли ТекДеньНедели = 7 Тогда

    ТекДеньНедели = 0;

    КонецЕсли;

    КонецЦикла;

    КонецПроцедуры
    Процедура ВычислитьРабДни(Команда) Начало2010 = НачалоГода(Год); Конец2010 = КонецГода(Год); ВсегоДней = Окр((Конец2010 – Начало2010)/(60*60*24)); Праздник0101 = 1; Праздник2302 = 31+23; Если ВсегоДней > 364 Тогда Праздник0803 = 31+29+8; Иначе Праздник0803 = 31+28+8; КонецЕсли; ТекДеньНедели = 0; РабДней = 0; Для Счетчик = 1 По ВсегоДней Цикл ТекДеньНедели = ТекДеньНедели + 1; Если ТекДеньНедели <> 6 И ТекДеньНедели <> 7 Тогда Если Счетчик <> Праздник0101 И Счетчик <> Праздник2302 И Счетчик <> Праздник0803 Тогда РабДней = РабДней + 1; КонецЕсли; ИначеЕсли ТекДеньНедели = 7 Тогда ТекДеньНедели = 0; КонецЕсли; КонецЦикла; КонецПроцедуры

  7. comradeegor 20.11.2010 в 16:10

    Написал 2 функции на сервере

    &НаСервере
    Функция ЕстьПраздникиВМесяце(Месяц)
    Возврат (Месяц = 1) ИЛИ (Месяц = 2) ИЛИ (Месяц = 3);
    КонецФункции // ЕстьПраздникиВМесяце()
    &НаСервере
    Функция ВыходныеВмесяце(Месяц)
    ЕстьПраздникиВМесяце(Месяц) – по номеру месяца возвращает логическое значение – есть ли в нём праздники или нет.
    Функция ВыходныеВмесяце(Месяц) – по номеру месяца возвращает массив выходных дней. Массив использован на случай,  если выходных в месяце несколько.
    Сама процедура проста и конечно не рациональна. Идёт цикл от 1 января 2010 и каждая дата проверяется – рабочая она или нет. Счетчик плюсуется.
    <code>&НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ТекущаяДата = Дата(2010, 1, 1);
    Для Год = 2010 По 2020 Цикл

    РабочихДней = 0;
    Для Месяц = 1 По 12 Цикл

    ЕстьПраздникиВМесяце = ЕстьПраздникиВМесяце(Месяц);
    ВыходныеВмесяце = ВыходныеВмесяце(Месяц);

    Пока Месяц(ТекущаяДата) = Месяц Цикл

    Если ЕстьПраздникиВМесяце Тогда

    Праздник = (ВыходныеВмесяце.Найти(День(ТекущаяДата)) <> Неопределено);

    КонецЕсли;

    Если ДеньНедели(ТекущаяДата) <> 6 И ДеньНедели(ТекущаяДата) <> 7 И НЕ Праздник Тогда
    РабочихДней = РабочихДней + 1;
    КонецЕсли;

    ТекущаяДата = ТекущаяДата + СекундВСутках;

    КонецЦикла;

    КонецЦикла;

    Сообщить(“В ” + Год + ” году ” + РабочихДней + ” рабочих дней.”);

    КонецЦикла;
    КонецПроцедуры
    </code>

    Можно было бы написать менее ресурсо затратно – посчитать количество полных недель, добавить остаток дней и вычесть выходные, но так было бы менее наглядно
    :)
    Например так:
    <code>&НаСервере
    Функция РабочихДнейВГоду(Год)

    ПервыйДень = Дата(Год, 1, 1);
    ДеньНеделиПервыйДень = ДеньНедели(ПервыйДень);

    ПоследнийДень = Дата(Год, 12, 31);
    ДеньНеделиПоследнийДень = ДеньНедели(ПоследнийДень);

    ДнейВГоду  = ДеньГода(ПоследнийДень);
    ПолныхНедель = (ДнейВгоду – ?(ДеньНеделиПервыйДень = 1, 0, 8 – ДеньНеделиПервыйДень) –
    ?(ДеньНеделиПоследнийДень = 7, 0, ДеньНеделиПоследнийДень)
    )/7;

    ОгрызокРабочихСначала = ?(ДеньНеделиПервыйДень > 5 ИЛИ ДеньНеделиПервыйДень = 1, 0, 5 – ДеньНеделиПервыйДень + 1);

    ОгрызокРабочихСконца  = ?(ДеньНеделиПоследнийДень=7, 0, ?(ДеньНеделиПоследнийДень = 6, 5, ДеньНеделиПоследнийДень));

    Возврат ПолныхНедель*5 + ОгрызокРабочихСначала + ОгрызокРабочихСконца –
    (ДеньНедели(Дата(Год, 1, 1)) < 6) – (ДеньНедели(Дата(Год, 2, 23)) < 6) – (ДеньНедели(Дата(Год, 3, 8)) < 6);

    КонецФункции // РабочихДнейВГоду()
    </code>

    Обратная связь:
    1. Новое – отличие 8.2 от 8.1, кое-что новое узнал о работе в конфигураторе – подбор типа для переменных и пр. фишки
    2. Затруднений особых не было. Непривычно было писать перед каждой процедурой на сервере, на клиенте
    3. Хотелось бы более подробно рассмотреть отличие клиента и сервера.

  8. Задание выполненно:
    Вопросы вызвали несколько моментов:
    1) по чему в результате ряда операторов
    ТекГод = ДОбавитьМесяц(ТекущийГод,12*СчетчикЛет);
    ГодСтр = Строка(Год(ТекГод));
    ГодСтр = СтрЗаменить(ГодСтр,” “,””);
    Итоговая строка ГодСтр = 2 010; то есть какой то непонятный пробел появляется?
    2)К структуре можно обратиться только по статичному ключу, те ВыхДни.2010,  нельзя как нибудь так ВыхДни.20 + ТекГод?
    Программный код:
    &НаКлиенте
    Процедура Сформировать(Команда)
    Для СчетчикЛет = 1 По 10 Цикл
    ТекГод = ДобавитьМесяц(ТекущийГод,СчетчикЛет * 12);

    ГодСтр = Строка(ТекГод);
    ГодСтр = Сред(ГодСтр,7,4);
    колРабДней = КоличествоРабочихДнейВГоду(ТекГод);
    ДнейВГоду = 365;
    Попытка
    Если дата(Число(ГодСтр),02,29) = неопределено Тогда
    ДнейВГоду = 366;
    КонецЕсли;
    Исключение
    ДнейВГоду = 366;
    КонецПопытки; СтруктВыходныеДни.Вставить(“Год” + ГодСтр,ДнейВГоду-колРабДней);
    Сообщить(” В ” + Год(ТекГод) + ” количество рабочих дней = ” + КоличествоРабочихДнейВГоду(ТекГод));
    КонецЦикла;
    КонецПроцедуры

    &НаКлиенте
    Функция КоличествоРабочихДнейВГоду(ДатаГода)
    НачГ = НачалоГода(ДатаГода);
    КонГ = КонецГода(ДатаГода);
    Праздники = Новый массив; Праздники.Добавить(Дата(Год(ДатаГода),01,01));
    Праздники.Добавить(Дата(Год(ДатаГода),02,23));
    Праздники.Добавить(Дата(Год(ДатаГода),03,08));
    колрабочихДней = 0;
    Счетчик = начГ;
    Пока Счетчик < КонГ Цикл
    ДеньПоСчетчику = (Деньнедели(Счетчик));
    Если ((ДеньПоСчетчику = 6) ИЛИ (ДеньПоСчетчику = 7)) Тогда
    Счетчик = Счетчик +СекундВДне;
    продолжить;
    КонецЕсли;

    ЭтоПраздник = Ложь;
    ЗнПраздника = “”;
    Для каждого ЗнПраздника Из Праздники Цикл
    Если ЗнПраздника = Счетчик Тогда
    ЭтоПраздник = Истина;
    прервать;
    КонецЕсли;
    КонецЦикла;

    Если ЭтоПраздник Тогда
    Счетчик = Счетчик +СекундВДне;
    продолжить;
    КонецЕсли;
    колрабочихДней = колрабочихДней + 1;
    Счетчик = Счетчик +СекундВДне;
    КонецЦикла;
    Возврат колрабочихДней;
    КонецФункции // КоличествоРабочихДнейВГоду()

    Ответы:
    1)Очень полезная информация по унарным операциям, и их приоритете, также считаю полезным для себя вопросы настройки ИБ
    2)В принципе все темы прошли нормально
    3)Это конечно не совсем имеет отношение к текущему блоку но хотелось бы, что бы в дальнейшем было освещено взаимодействие баз на 8.2 с 8.1, 7.7, т.е обмен через OLE, xml  и тому подобные вещи..

    • Ответы на оба вопроса вы найдете в решении ДЗ №4.

    • dmitry.mazaev 18.11.2010 в 20:17

      Процедура КнопкаВыполнитьНажатие(Кнопка)

      Для НомерГода = 2010 По 2019 Цикл
      КолРабочих = 0;
      Для НомерМесяца = 1 По 12 Цикл
      ПоМесяцу = 0;
      КолДнейМесяца = ДеньГода(КонецМесяца(Дата(НомерГода, НомерМесяца, 1))) – ДеньГода(НачалоМесяца(Дата(НомерГода, НомерМесяца, 1))) + 1;
      Для НомерДня = 1 По КолДнейМесяца Цикл
      ТекДата = Дата(НомерГода, НомерМесяца, НомерДня);
      Если НачалоДня(ТекДата) = НачалоДня(Дата(НомерГода, 1, 1)) ИЛИ
      НачалоДня(ТекДата) = НачалоДня(Дата(НомерГода, 2, 23)) ИЛИ
      НачалоДня(ТекДата) = НачалоДня(Дата(НомерГода, 3, 8)) Тогда
      Продолжить;
      Иначе

      Если ДеньНедели(Дата(НомерГода, НомерМесяца, НомерДня)) < 6 Тогда
      КолРабочих = КолРабочих + 1;
      ПоМесяцу = ПоМесяцу + 1;
      КонецЕсли;
      КонецЕсли;
      КонецЦикла;
      КонецЦикла;
      Сообщить(“Год: ” + Формат(НомерГода, “ЧГ=0″) + ” рабочих дней: ” + КолРабочих);
      КонецЦикла;
      КонецПроцедуры
      Результаты:
      Год: 2010 рабочих дней: 258
      Год: 2011 рабочих дней: 258
      Год: 2012 рабочих дней: 259
      Год: 2013 рабочих дней: 259
      Год: 2014 рабочих дней: 260
      Год: 2015 рабочих дней: 259
      Год: 2016 рабочих дней: 258
      Год: 2017 рабочих дней: 258
      Год: 2018 рабочих дней: 258
      Год: 2019 рабочих дней: 259

      1. Новое узнал об унарных операциях.
      2. Как таковых затруднений не было
      3.  Хотелось бы узнать поподробнее про механизмы отладки и тестирование производительности конфигурации.

      • dmitry.mazaev 18.11.2010 в 20:21

        Переменная “ПоМесяцу” была вставлена в отладочных целях.

      • Об отладке мы говорим в 1-ом блоке базового и 0-вом блоке продвинутого.
        А о производительности подробно рассуждаем в 1-ом блоке продвинутого курса.
        Но вообще любой код даже базового курса стараемся писать оптимальным (например в ДЗ).

  9. &НаКлиенте
    Процедура ВыполнитьНажатие(Команда)
    РасчетныйГод = КонецГода(Объект.Дата);
     
    ВыходныеДни = Новый Структура;
     
    Для Н = 0 По  9 Цикл
     
    РасчетныйГод = ?(Н = 0,РасчетныйГод,ДобавитьМесяц(РасчетныйГод,12));
    РассчитатьРабочиеДни(РасчетныйГод, ВыходныеДни);
     
    КонецЦикла;
     
    Сообщить(ВыходныеДни.Год2014);
     
    КонецПроцедуры
     
    Функция РассчитатьРабочиеДни(РасчетныйГод, ВыходныеДни)
     
    ДнейВГоду = ДеньГода(РасчетныйГод);
    ВыходныхВГоду = НеделяГода(РасчетныйГод) * 2;
    ПраздниковВГоду = ПолучитьЧислоПраждников(РасчетныйГод);
    РабочихДнейВГоду = ДнейВГоду – (ВыходныхВГоду + ПраздниковВГоду);
    Сообщить(“В ” + Формат(Год(РасчетныйГод),”ЧГ=0″) + ” году” + ” – ” + РабочихДнейВГоду + ” рабочих дней” );
    //
    Ключ = “Год” + Строка(Формат(Год(РасчетныйГод),”ЧГ=0″));
    Выходные = ВыходныхВГоду + ПраздниковВГоду;
    ВыходныеДни.Вставить(Ключ , Выходные);
    Возврат ВыходныеДни;
     
    КонецФункции
     
    Функция ПолучитьЧислоПраждников(РасчетныйГод)
     
    НомерГода = Строка(Формат(Год(РасчетныйГод),”ЧГ=0″));
    Массив = Новый Массив;
    Массив.Добавить(“0101”);
    Массив.Добавить(“0223”);
    Массив.Добавить(“0308”);
     
    Праздников = 0;
    Для Каждого Строка Из Массив Цикл
    ДеньНедели = ДеньНедели(Дата(НомерГода + Строка)) ;
    Если ДеньНедели = 6 ИЛИ ДеньНедели = 7 Тогда
     
    Праздников = Праздников + 1;
     
    КонецЕсли;
     
    КонецЦикла;
     
    Возврат Праздников;
     
    КонецФункции // ПолучитьЧислоПраждников()()
    Обратная связь:
    1) Новое для меня построение логических условий, как в одном из примеров решения ДЗ  и различие между операторм присваивания и сравнения. Четко не понимал разницу.
    2) Особых трудностей не было
    3) Какую тему раскрыть шире? Возможно виды учета,  Еще мне кажется подробнее про особенности работы  процедуры и функуции будет полезно. Так как фактически сказана одна фраза что процедура – выполнение кода, а функция – выполнение кода и возврат какого либо значение.  Я долго доходил до того  что если функция возвращает коллекцию значений переданную в нее, то ее не обязательно принимать в отдельную переменную.

  10. &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    НачДата = ‘2010.01.01’;
    Сутки = 60*60*24;
    ВыходныеДни = Новый Структура;

    Для СчетчикЛет = 1 По 10 Цикл
    НачДата = ДобавитьМесяц(НачДата,12);
    КоличествоРабочихДней = 0;
    КоличествоДнейВГоду = ДеньГода(КонецГода(НачДата));

    Для Счетчик = 1 По КоличествоДнейВГоду Цикл
    ТекущаяДата = НачДата + (Счетчик-1)*Сутки;
    Если (ДеньНедели(ТекущаяДата)>5) 
    ИЛИ ((День(ТекущаяДата)=1) И (Месяц(ТекущаяДата)=1))
    ИЛИ ((День(ТекущаяДата)=23) И (Месяц(ТекущаяДата)=2))
    ИЛИ ((День(ТекущаяДата)=8) И (Месяц(ТекущаяДата)=3)) Тогда
    Продолжить;
    КонецЕсли;
    КоличествоРабочихДней = КоличествоРабочихДней + 1;
    КонецЦикла;
    Сообщить(“”+Год(НачДата)+” год – “+КоличествоРабочихДней+” рабочих дней”);

    ИмяКлюча = “Год”+Формат(Год(НачДата),”ЧГ=0”);
    ВыходныеДни.Вставить(ИмяКлюча,КоличествоДнейВГоду – КоличествоРабочихДней);
    Сообщить(ВыходныеДни[ИмяКлюча]);
    КонецЦикла;
    КонецПроцедуры
    1)Узнал новое: особенности платформы 8.2, сервисные средства для написания кода, преобразование типов данных, навигация по циклу или условию.
    2) Сильных затруднений не было, учусь на своих ошибках.
    3) Да, жаль что клиент-сервер – в продвинутом блоке.

  11. Сделала, отдельно проанализировав первый/последний дни года и праздники на предмет их “рабочести”. Немного буксовала на структуре, для меня не очевидный тип данных оказался.
    ===
    1. В основном, упорядочились уже имеющиеся знания и навыки,  вспомнилось кое-что подзабытое или упускаемое из виду.
    2.  Так чтоб уж совсем “затруднения” -не было, материал хорошо и понятно изложен.
    3. Пока нет.

  12. Андрей 14.11.2010 в 20:49

    Сделал. собственно говоря обычное задание. Особых трудностей нет, основной небольшой “напряг” переход на управляемые формы :-)

  13. Сделал все в одной процедуре.(побыстрому). Можете затестить…

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    ВыходныеДни = Новый Структура;

    ДатаНачалаПериода = ‘20100101’;
    ДатаОкончанияПериода = КонецГода(‘20201231’);

    ДатаИтератор = КонецГода(ДатаНачалаПериода);

    Пока ДатаИтератор <= ДатаОкончанияПериода Цикл

    ТекГод = “Год”+Формат(Год(ДатаИтератор),”ЧГ=0”);
    ВыходныеДни.Вставить(ТекГод,Новый Структура(“Наименование, Дней”,””,0));
    ВыходныеДни[ТекГод].Наименование = Формат(Год(ДатаИтератор),”ЧГ=0″);
    ДатаИтератор = КонецГода(ДатаИтератор+1);

    КонецЦикла;

    ДатаИтератор = НачалоГода(ДатаНачалаПериода);
    Пока ДатаИтератор <= ДатаОкончанияПериода Цикл

    ДеньМесяца = (ДатаИтератор-НачалоМесяца(ДатаИтератор))/(3600*24)+1;
    ТекГод = “Год”+Формат(Год(ДатаИтератор),”ЧГ=0”);

    Если ДеньНедели(ДатаИтератор)<> 6
    И ДеньНедели(ДатаИтератор)<> 7
    И ДеньГода(ДатаИтератор)<>1
    И НЕ (Месяц(ДатаИтератор)=2 И ДеньМесяца=23)
    И НЕ (Месяц(ДатаИтератор)=3 И ДеньМесяца=8) Тогда

    ВыходныеДни[ТекГод].Дней=ВыходныеДни[ТекГод].Дней + 1;

    КонецЕсли;

    ДатаИтератор = ДатаИтератор + 3600*24;

    КонецЦикла;

    Для Каждого Год Из ВыходныеДни Цикл

    СтрСообщения = НСтр(“ru=’%Год% год – %Дней% рабочих дней'”);
    СтрСообщения = СтрЗаменить(СтрСообщения, “%Год%”, Год.Значение.Наименование);
    СтрСообщения = СтрЗаменить(СтрСообщения, “%Дней%”, Год.Значение.Дней);
    Сообщить(СтрСообщения);

    КонецЦикла;

    КонецПроцедуры
    &НаСервереПроцедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ВыходныеДни = Новый Структура; ДатаНачалаПериода = ‘20100101’; ДатаОкончанияПериода = КонецГода(‘20201231’); ДатаИтератор = КонецГода(ДатаНачалаПериода); Пока ДатаИтератор <= ДатаОкончанияПериода Цикл ТекГод = “Год”+Формат(Год(ДатаИтератор),”ЧГ=0”); ВыходныеДни.Вставить(ТекГод,Новый Структура(“Наименование, Дней”,””,0));    ВыходныеДни[ТекГод].Наименование = Формат(Год(ДатаИтератор),”ЧГ=0″);    ДатаИтератор = КонецГода(ДатаИтератор+1); КонецЦикла; ДатаИтератор = НачалоГода(ДатаНачалаПериода); Пока ДатаИтератор <= ДатаОкончанияПериода Цикл ДеньМесяца = (ДатаИтератор-НачалоМесяца(ДатаИтератор))/(3600*24)+1; ТекГод = “Год”+Формат(Год(ДатаИтератор),”ЧГ=0”); Если ДеньНедели(ДатаИтератор)<> 6  И ДеньНедели(ДатаИтератор)<> 7  И ДеньГода(ДатаИтератор)<>1 И НЕ (Месяц(ДатаИтератор)=2 И ДеньМесяца=23) И НЕ (Месяц(ДатаИтератор)=3 И ДеньМесяца=8) Тогда ВыходныеДни[ТекГод].Дней=ВыходныеДни[ТекГод].Дней + 1; КонецЕсли; ДатаИтератор = ДатаИтератор + 3600*24; КонецЦикла; Для Каждого Год Из ВыходныеДни Цикл СтрСообщения = НСтр(“ru=’%Год% год – %Дней% рабочих дней'”); СтрСообщения = СтрЗаменить(СтрСообщения, “%Год%”, Год.Значение.Наименование); СтрСообщения = СтрЗаменить(СтрСообщения, “%Дней%”, Год.Значение.Дней); Сообщить(СтрСообщения); КонецЦикла; КонецПроцедуры

    • Что-то код вставился два раза… (будьте внимательней). Нужно реализовать на форуме возможность редактирования комментария…

      • В ToDo записано, но быстро сделать нельзя – из соображений безопасности нельзя корректировать одобренные комментарии

  14. Выполнил обычным перебором дней.
    1.Очень полезные оказались материалы со *
    2. затруднений не было
    3. Блок легкий, все понятно, интересны пасхальные яйца.

  15. //P.S. Нашел ошибку
    Надо :
    КолРабочих =365+Дней366-КолВыходных

  16. //Т.к. 365дней/7дней = 52(недели) и 1 день, то чтобы захватить еще один выходной
    //надо чтобы год заканчивался на субботу или воскресенье. (Добавляется 1 день)
    //Для 366 дней –  конец в субботу – тоже  +1 день, конец в воскр. + 2 дня
    //Для 366 дней – конец в понед. – тоже  +1 день  т.к. начался он в субботу
    &НаКлиенте
    Процедура Команда1(Команда)  
     КолВЫХОДНЫХ_в_52_нед = 52*2;
     ВыходныеДни = Новый Структура();
      Для сч = Год(ТекущаяДата()) По Год(ТекущаяДата()) + 10 Цикл 
      КолВЫХОДНЫХ = КолВЫХОДНЫХ_в_52_нед + Праздники(сч);
         Дней366 = ВысокосныйГод(сч);
      Если ДеньНедели(Дата(сч,12,31))=6 Тогда
        //+1 для 365,366
      ИначеЕсли ДеньНедели(Дата(сч,12,31))=7 Тогда
       КолВЫХОДНЫХ = КолВЫХОДНЫХ+1+Дней366 
      ИначеЕсли ДеньНедели(Дата(сч,12,31))=1 Тогда
       КолВЫХОДНЫХ = КолВЫХОДНЫХ+Дней366
      КонецЕсли;
      КолРабочих = 365-КолВЫХОДНЫХ;
      Сообщить(Формат(сч,”ЧГ=0″)+”год – “+КолРабочих+” рабочих дней”);
      ВыходныеДни.Вставить(“Год”+Формат(сч,”ЧГ=0”),КолВЫХОДНЫХ);
      
     КонецЦикла;
     Сообщить(ВыходныеДни.Год2014);
    КонецПроцедуры
    &НаКлиенте
    Функция Праздники(Год);
     ПраздникиНеВыходные = 0;
     Массив = Новый Массив(3);
     Массив[0] = Дата(Год,1,1);
     Массив[1] = Дата(Год,2,23);
        Массив[2] = Дата(Год,3,8);
     Для сч=0 По Массив.ВГраница() Цикл
         Если ДеньНедели(Массив[сч]) <6 Тогда
           ПраздникиНеВыходные = ПраздникиНеВыходные+1  
      КонецЕсли;  
     КонецЦикла;  
        Возврат ПраздникиНеВыходные  
    КонецФункции
    &НаКлиенте
    Функция ВысокосныйГод(Год);
     Если День(КонецДня(Дата(Год,2,28))+1) = 29 Тогда
          Возврат 1
      Иначе
       Возврат 0
     КонецЕсли; 
    КонецФункции
    P.S. еще не закончил изучать 0-блок, но то что успел 
    все интересно
    спасибо

  17. &НаСервере
    Перем Структура;
    &НаСервере
    Процедура РассчитатьРабочиеДни(ТекущийГод)
     ПраздничныхВыходныйДней = 1;    //1 января – праздничный день
     РабочихДней = 0;
     ДатаОкончанияГода = КонецГода(Дата(ТекущийГод, 12, 31)); 
     ТекущийДень = Дата(Дата(ТекущийГод, 01, 02));
     Пока  ТекущийДень <= ДатаОкончанияГода Цикл   
      Если ДеньНедели(ТекущийДень) > 5 Тогда
       ПраздничныхВыходныйДней = ПраздничныхВыходныйДней + 1;
      ИначеЕсли (День(ТекущийДень)= 8 И Месяц(ТекущийДень)=3) ИЛИ (День(ТекущийДень)= 23 И Месяц(ТекущийДень)=2) Тогда
       ПраздничныхВыходныйДней = ПраздничныхВыходныйДней + 1;
      Иначе
       РабочихДней = РабочихДней + 1;
      КонецЕсли;
         ТекущийДень = ТекущийДень + 24 * 60 * 60;
     КонецЦикла;
     Сообщить(Строка(ТекущийГод) + ” – ” + Строка(РабочихДней) + ” рабочих дней”);
     Структура.Вставить(“Год”+Формат(ТекущийГод,”ЧГ=0”),ПраздничныхВыходныйДней);
    КонецПроцедуры
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
     
     Перем ЗначениеСтруктуры;
     
     ТекущийГод = Год(ТекущаяДата());
     Для х = 1 По 10 Цикл
      РассчитатьРабочиеДни(ТекущийГод);
      ТекущийГод = ТекущийГод + 1;
     КонецЦикла; 
     
     Сообщить(“================Вывод праздничных и выходных дней”);
     Для каждого ЭлементСтруктуры Из Структура Цикл
      Сообщить(ЭлементСтруктуры.Ключ+” – “+ЭлементСтруктуры.Значение)
     КонецЦикла;
    КонецПроцедуры
     
    Структура = Новый Структура;

  18. Особых затруднений нет – буквально намедни писал аналогичный “боевой” алгоритм

  19. &НаКлиенте
    Процедура ВычислитьРабочиеДни(Команда)
    // Вставить содержимое обработчика.
    текГод = Год(ТекущаяДата());

    СтруктураВыходныхДней = Новый Структура;
    Для сч = 1 По 10 Цикл
    РабочихДней = 0;
    ВыходныхДней = 0;

    РассчитатьКоличествоРабочихВыходныхДней(текГод, РабочихДней, ВыходныхДней);

    стртекГод = Формат(текГод, “ЧГ=0”);

    СтруктураВыходныхДней.Вставить(“Год” + стртекГод, ВыходныхДней);

    Сообщить(“Год ” + текГод + ” раб.дней ” + РабочихДней);
    Сообщить(“Год ” + текГод + ” вых.дней ” + СтруктураВыходныхДней[“Год” + стртекГод]);

    текГод = текГод + 1;
    КонецЦикла;
    КонецПроцедуры

    Процедура РассчитатьКоличествоРабочихВыходныхДней(текГод, РабочихДней, ВыходныхДней)
    ОдинДень = 24 * 60 * 60;

    НачалоГода = Дата(текГод ,01,01); //начало года
    КонецГода = КонецГода(НачалоГода); //конец года

    НачалоПервойНедели = КонецНедели(НачалоГода) + 1;
    НачалоПоследнейНедели = НачалоНедели(КонецГода);
    ПолныхНедель = (НачалоПоследнейНедели – НачалоПервойНедели) / (7 * ОдинДень);

    РабДнейДоПервойНедели = ?(ДеньНедели(НачалоГода) > 5,0,6 – ДеньНедели(НачалоГода));
    РабДнейПоследнейНедели = Мин(ДеньНедели(КонецГода),5);

    РабочихДней = ПолныхНедель * 5
    + РабДнейДоПервойНедели
    + РабДнейПоследнейНедели
    + ?(ДеньНедели(НачалоГода) < 6, -1,0) //1 января
    + ?(ДеньНедели(Дата(текГод ,02,23)) < 6, -1,0) //23 февраля
    + ?(ДеньНедели(Дата(текГод ,03,08)) < 6, -1,0); //08 марта

    ВыходныхДней = ДеньГода(КонецГода) – РабочихДней;
    КонецПроцедуры
     
    коммент в 22.04 использовался не оптимальный код (обход по циклу).
    этот считаю оптимальным.
    1 января можно было считать сразу выходным, но для единообразия включил его в расчет рабочих дней.

  20. &НаКлиенте
    Процедура ВычислитьРабочиеДни(Команда)
    // Вставить содержимое обработчика.
    текГод = Год(ТекущаяДата());

    СтруктураВыходныхДней = Новый Структура;
    Для сч = 1 По 10 Цикл
    РабочихДней = 0;
    ВыходныхДней = 0;

    РассчитатьКоличествоРабочихВыходныхДней(текГод, РабочихДней, ВыходныхДней);

    стртекГод = Формат(текГод, “ЧГ=0”);

    СтруктураВыходныхДней.Вставить(“Год” + стртекГод, ВыходныхДней);

    Сообщить(“Год ” + текГод + ” раб.дней ” + РабочихДней);
    Сообщить(“Год ” + текГод + ” вых.дней ” + СтруктураВыходныхДней[“Год” + стртекГод]);

    текГод = текГод + 1;
    КонецЦикла;
    КонецПроцедуры

    Процедура РассчитатьКоличествоРабочихВыходныхДней(текГод, РабочихДней, ВыходныхДней)

    текДата = Дата(текГод ,01,01); //начало года
    КонецГода = КонецГода(ТекДата);

    ОдинДень = 24 * 60 * 60;

    //праздники
    Янв1 = текДата;
    Февр23 = ДобавитьМесяц(текДата,1) + 22 * ОдинДень;
    Март8 = ДобавитьМесяц(текДата,2) + 7 * ОдинДень;

    Пока текДата <=КонецГода Цикл
    Если текДата = Янв1
    или текДата = Февр23
    или текДата = Март8 Тогда
    Иначе
    текДень = ДеньНедели(текДата);
    Если текДень < 6 Тогда
    РабочихДней = РабочихДней + 1;
    КонецЕсли;
    КонецЕсли;

    текДата = текДата + ОдинДень;
    КонецЦикла;

    ВыходныхДней = ДеньГода(КонецГода) – РабочихДней;
    КонецПроцедуры

  21. Функция ПолучитьКоличествоРабочихДней(ТекГод)
    ПервыйДень = НачалоГода(ТекГод+”0101″);
    ПоследнийДень = КонецГода(ТекГод+”0101″);

    ТекДата = ПервыйДень;

    КолРабДней = 0;

    Пока ТекДата<ПоследнийДень Цикл

    ТекДата = ТекДата+(60*60*24);

    //проверка на 1 января,23 февраля и 8 марта
    Если (НачалоДня(ТекДата) = НачалоДня(ТекГод+”0101″)) или (НачалоДня(ТекДата) = НачалоДня(ТекГод+”0223″)) или (НачалоДня(ТекДата) = НачалоДня(ТекГод+”0308″)) Тогда
    Продолжить;
    КонецЕсли;

    ТекДеньНедели = ДеньНедели(ТекДата);

    //проверка насубботу и всокресенье
    Если (ТекДеньНедели = 6) или (ТекДеньНедели = 7) Тогда
    Продолжить;
    КонецЕсли;

    КолРабДней = КолРабДней + 1;

    КонецЦикла;

    Возврат КолРабДней;
    КонецФункции // ()

    &НаКлиенте
    Процедура Сформировать(Команда)

    ВыходныеДни = Новый Структура;

    ТекГод = “2010”;
    КолДней = ПолучитьКоличествоРабочихДней(ТекГод);
    Сообщить(ТекГод+” – “+КолДней+” рабочих дней”);
    ВыходныеДни.Вставить(“Год2010”,КолДней);

    ТекГод = “2011”;
    КолДней = ПолучитьКоличествоРабочихДней(ТекГод);
    Сообщить(ТекГод+” – “+КолДней+” рабочих дней”);
    ВыходныеДни.Вставить(“Год2011”,КолДней);

    ТекГод = “2012”;
    КолДней = ПолучитьКоличествоРабочихДней(ТекГод);
    Сообщить(ТекГод+” – “+КолДней+” рабочих дней”);
    ВыходныеДни.Вставить(“Год2012”,КолДней);

    Сообщить(ВыходныеДни.Год2010);
    Сообщить(ВыходныеДни.Год2011);
    Сообщить(ВыходныеДни.Год2012);

    КонецПроцедуры
    Обратная связь.
    1. В целом в третьем блоке все было известно. Разве что использование “=”.
    2. Много вопросов по клиент-серверу, но я так понимаю это не в этом курсе.
    3.  Опять же по клиент-серверу.

    • 1. Вы уже третий посмотрели :) Смысл я понял )
      2. Да верно, в продвинутом.