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

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

 

 

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

См. также

Вставляем картинку из буфера обмена (платформа 1С 8.3.24)

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

1 стартмани

18.03.2024    2664    0    John_d    8    

53

GUID в 1С 8.3 - как с ними быть

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

12.02.2024    4595    atdonya    22    

45

Переоткрытие внешних обработок

Универсальные функции Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    3956    ke.92@mail.ru    16    

61

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    8802    YA_418728146    6    

141

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2071    21    progmaster    7    

3

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    16140    133    sapervodichka    112    

129

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7242    quazare    8    

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

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

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