Получение даты, зная день недели и его порядок в месяце

Иногда бывает необходимость получить «Первый понедельник месяца» или «Вторую пятницу месяца».
Есть несколько способов решения вопроса. Опишу один из них.

Изобретать велосипед неохота никому, но то ли я гуглом пользоваться не умею, то ли авторы статью пишут не с теми ключевыми словами.

Один из хороших вариантов решения описан в статье Номер дня недели в месяце.

Мой вариант выглядит следующим образом


// Функция - Получить день недели в месяце
//
// Параметры:
//  Неделя  - Число - Порядковый номер недели в месяце (1, 2, 3, 4)
//  ДеньНедели  - Число - День недели, где 1 - Понедельник, ..., 7 - Воскресенье
//  ЗаданнаяДатаМесяца - Дата - Дата месяца, для которой необходимо получить дату дня
//
// Возвращаемое значение:
// Дата - Если она существует или Неопределено
//
Функция ПолучитьДеньНеделиВМесяце(Неделя, ДеньНедели, ЗаданнаяДатаМесяца)

Результат = Неопределено;

ПервыйДеньМесяца = НачалоМесяца(ЗаданнаяДатаМесяца);   // 11.09.17 - > 01.09.17
ПервыйДеньНеделиМесяца = ДеньНедели(ПервыйДеньМесяца);  // 01.09.17 - > 5 (Пятница)
СмещениеДняНеделиМесяца = ДеньНедели - ПервыйДеньНеделиМесяца; // 1 - 5 = -4 (Смещение для понедельника)

Если СмещениеДняНеделиМесяца < 0 Тогда
СмещениеДняНеделиМесяца = 7 + СмещениеДняНеделиМесяца; // если получили отрицательное значение, то прибавляем неделю  7-4=3
КонецЕсли;

ИскомаяДатаДня = 7*(Неделя-1) + СмещениеДняНеделиМесяца + 1; // Находим день 7*(1-1) + 3 + 1 = 4

Попытка
Результат = Дата(Год(ЗаданнаяДатаМесяца), Месяц(ЗаданнаяДатаМесяца), ИскомаяДатаДня); // Пытаемся преобразовать
Исключение
Результат = Неопределено; // такой даты не существует (Например 7ой понедельник месяца)
КонецПопытки;

Возврат Результат;

КонецФункции

 

 

9 Comments

  1. echo77

    Из практического применения вспомнилось только как найти последнюю пятницу июля

    Reply
  2. Synoecium

    запросом проще, имхо:

    ВЫБРАТЬ
    ВЫБОР
    КОГДА ДЕНЬНЕДЕЛИ(НАЧАЛОПЕРИОДА(&ЗаданнаяДатаМесяца, МЕСЯЦ)) <= &ДеньНедели
    ТОГДА ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&ЗаданнаяДатаМесяца, МЕСЯЦ), НЕДЕЛЯ, &Неделя — 1), НЕДЕЛЯ), ДЕНЬ, &ДеньНедели — 1)
    ИНАЧЕ ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&ЗаданнаяДатаМесяца, МЕСЯЦ), НЕДЕЛЯ, &Неделя), НЕДЕЛЯ), ДЕНЬ, &ДеньНедели — 1)
    КОНЕЦ КАК ДатаРезультат
    Reply
  3. 987ww765

    (2) Проще, не спорю. Даже привел статью, где рассматривается этот вариант. Просто это другой вариант решения.

    Reply
  4. 987ww765

    (3) Шикарное решение. Снимаю шляпу. Сам бы я не додумался до такого(

    Reply
  5. spacecraft

    (3) интересный алгоритм. Только не правильно отрабатывает на параметрах вне диапазона. Точнее если указать параметры меньше допустимого для данного месяца.

    Пример:

    ДатаМесяц = Дата(2017,1,1);

    НомерНеделиМесяца = 1;

    НомерДняНедели = 1;

    Получим ‘02.01.2017’.

    В большую сторону отрабатывает.

    Это конечно проблема передачи корректных данных, но забавно.

    Reply
  6. ildarovich

    (6) А мне кажется, что результат верный, ведь спрашивается дата первого понедельника месяца (как я понял задачу). Это и есть второе января.

    Reply
  7. spacecraft

    (7) если так подходить к задаче, тогда верно. Только получается, что начало первой недели больше конца первой недели. Логический нонсенс.

    Reply
  8. ildarovich

    (8) Да, согласен, наверное, мне нужно было по другому функцию и параметры называть…ближе к формулировке задачи в анонсе.

    Reply
  9. FesenkoA

    (1)єто вы с бюджетниками никогда не работали)))

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *