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

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

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

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

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


// Функция - Получить день недели в месяце
//
// Параметры:
//  Неделя  - Число - Порядковый номер недели в месяце (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 не будет опубликован. Обязательные поля помечены *