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

12.09.17

Разработка - Универсальные функции

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

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

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

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


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

 

 

Вступайте в нашу телеграмм-группу Инфостарт

Первый второй последний понедельник вторник пятница день месяца

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    4827    Abysswalker    11    

47

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.

14.05.2025    9027    DeerCven    15    

63

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    57918    dimanich70    85    

175

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    8138    7    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    72665    atdonya    31    

73

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    10112    ke.92@mail.ru    17    

68
Отзывы
3. ildarovich 8057 13.09.17 12:48 Сейчас в теме
Вот еще вариант:
Функция ПолучитьДатуПоНомерамДня_и_НеделиМесяца(НомерНеделиМесяца, НомерДняНедели, ДатаМесяца)
	
	Возврат НачалоМесяца(ДатаМесяца) 
+ 86400 * (7 * НомерНеделиМесяца - 7 + (НомерДняНедели - ДеньНедели(НачалоМесяца(ДатаМесяца)) + 7) % 7)
	
КонецФункции
В функции, приведенной в статье, мне не нравится "Попытка-Исключение", которую лучше не использовать для относительно простой календарной арифметики, а оставить для более серьезных и сложных случаев. И то, что возвращается в исключении. Если результат функции будет без проверки на неопределено использоваться в выражении, то получится еще одно исключение. А если делать проверку, то она будет еще одной.
Irwin; TerveRus; Deslime; +3 Ответить
Остальные комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. echo77 1938 13.09.17 05:41 Сейчас в теме
Из практического применения вспомнилось только как найти последнюю пятницу июля
10. FesenkoA 60 06.04.18 09:37 Сейчас в теме
(1)єто вы с бюджетниками никогда не работали)))
2. Synoecium 793 13.09.17 08:55 Сейчас в теме
запросом проще, имхо:
ВЫБРАТЬ
	ВЫБОР
		КОГДА ДЕНЬНЕДЕЛИ(НАЧАЛОПЕРИОДА(&ЗаданнаяДатаМесяца, МЕСЯЦ)) <= &ДеньНедели
			ТОГДА ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&ЗаданнаяДатаМесяца, МЕСЯЦ), НЕДЕЛЯ, &Неделя - 1), НЕДЕЛЯ), ДЕНЬ, &ДеньНедели - 1)
		ИНАЧЕ ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&ЗаданнаяДатаМесяца, МЕСЯЦ), НЕДЕЛЯ, &Неделя), НЕДЕЛЯ), ДЕНЬ, &ДеньНедели - 1)
	КОНЕЦ КАК ДатаРезультат
4. 987ww765 310 13.09.17 13:03 Сейчас в теме
(2) Проще, не спорю. Даже привел статью, где рассматривается этот вариант. Просто это другой вариант решения.
3. ildarovich 8057 13.09.17 12:48 Сейчас в теме
Вот еще вариант:
Функция ПолучитьДатуПоНомерамДня_и_НеделиМесяца(НомерНеделиМесяца, НомерДняНедели, ДатаМесяца)
	
	Возврат НачалоМесяца(ДатаМесяца) 
+ 86400 * (7 * НомерНеделиМесяца - 7 + (НомерДняНедели - ДеньНедели(НачалоМесяца(ДатаМесяца)) + 7) % 7)
	
КонецФункции
В функции, приведенной в статье, мне не нравится "Попытка-Исключение", которую лучше не использовать для относительно простой календарной арифметики, а оставить для более серьезных и сложных случаев. И то, что возвращается в исключении. Если результат функции будет без проверки на неопределено использоваться в выражении, то получится еще одно исключение. А если делать проверку, то она будет еще одной.
Irwin; TerveRus; Deslime; +3 Ответить
5. 987ww765 310 13.09.17 13:16 Сейчас в теме
(3) Шикарное решение. Снимаю шляпу. Сам бы я не додумался до такого(
6. spacecraft 13.09.17 13:53 Сейчас в теме
(3) интересный алгоритм. Только не правильно отрабатывает на параметрах вне диапазона. Точнее если указать параметры меньше допустимого для данного месяца.
Пример:
ДатаМесяц = Дата(2017,1,1);
НомерНеделиМесяца = 1;
НомерДняНедели = 1;
Получим '02.01.2017'.
В большую сторону отрабатывает.
Это конечно проблема передачи корректных данных, но забавно.
7. ildarovich 8057 13.09.17 14:27 Сейчас в теме
(6) А мне кажется, что результат верный, ведь спрашивается дата первого понедельника месяца (как я понял задачу). Это и есть второе января.
8. spacecraft 13.09.17 14:39 Сейчас в теме
(7) если так подходить к задаче, тогда верно. Только получается, что начало первой недели больше конца первой недели. Логический нонсенс.
9. ildarovich 8057 13.09.17 16:10 Сейчас в теме
(8) Да, согласен, наверное, мне нужно было по другому функцию и параметры называть...ближе к формулировке задачи в анонсе.
13. TerveRus 09.06.21 16:38 Сейчас в теме
(9) да, тут не номер недели задается, а порядковый номер нужного дня недели в месяце. То есть первый понедельник, а не понедельник первой недели. Если месяц начинается не с понедельника, или любой другой день недели не попадает в первую неделю, то всегда будет сдвиг номера недели)

Ну и этой функции пофиг, она получает хоть 10-й понедельник месяца, что может сбивать с толку)
А на самом деле, это 10-й понедельник от начала месяца заданной даты.

А так спасибо, пригодилось!
11. Slypower 3 19.06.20 12:23 Сейчас в теме
А есть обратная функция?
12. Slypower 3 19.06.20 12:28 Сейчас в теме
(11)Сам спросил, сам понял. Нужно было вот это
""+НеделяГода(ЭтаФорма.ДатаМесяца)+""+ДеньНедели(ЭтаФорма.ДатаМесяца)
Для отправки сообщения требуется регистрация/авторизация