Поиск даты от текущей за вычетом выходных дней

Программирование - Практика программирования

9
Простой способ поиска даты от текущей за вычетом выходных дней.

Иногда возникает ситуация что нужно к текущей дате добавить несколько дней, и найти дату что наступит через эти дни. Нет проблем когда это нужно сделать без учета рабочих и выходных дней.

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

В данном примере приведен простой запрос который ищет день, который наступит через определенное количество дней за вычетом выходных дней. То есть допустим мне нужно добавить 5 дней, до текущей даты - 28.11.2018, данное число у меня приходится на среду, выходные дни - суббота и воскресенье. Фактически +5 дней это следующую рабочую неделю 5.12.2018.

  • Фактически мы передаем в запрос дату от которой будем считать дни
  • Ищем по номеру дня дату которая наступит через n - дней от даты среза, за вычетом выходных дней

Данный запрос помогает решить данную проблему:

ВЫБРАТЬ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК Дата,
	РегламентированныйПроизводственныйКалендарь.ВидДня
ПОМЕСТИТЬ ВТ1
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря >= &ДатаСреза
	И РегламентированныйПроизводственныйКалендарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ11.Дата) КАК НомерДня,
	ВТ1.Дата,
	ВТ1.ВидДня
ИЗ
	ВТ1 КАК ВТ1
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ1 КАК ВТ11
		ПО ВТ1.Дата > ВТ11.Дата

СГРУППИРОВАТЬ ПО
	ВТ1.Дата,
	ВТ1.ВидДня

ИМЕЮЩИЕ
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ11.Дата) = &НомерДня

УПОРЯДОЧИТЬ ПО
	НомерДня

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

ВЫБРАТЬ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК Дата,
	РегламентированныйПроизводственныйКалендарь.ВидДня
ПОМЕСТИТЬ ВТ1
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
	ВЫБОР
			КОГДА &НомерДня > 0
				ТОГДА РегламентированныйПроизводственныйКалендарь.ДатаКалендаря >= &ДатаСреза
			ИНАЧЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря <= &ДатаСреза
		КОНЕЦ
	И РегламентированныйПроизводственныйКалендарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВЫБОР
		КОГДА &НомерДня > 0
			ТОГДА КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ11.Дата)
		ИНАЧЕ -КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ11.Дата)
	КОНЕЦ КАК НомерДня,
	ВТ1.Дата,
	ВТ1.ВидДня
ПОМЕСТИТЬ ВТ2
ИЗ
	ВТ1 КАК ВТ1
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ1 КАК ВТ11
		ПО (ВЫБОР
				КОГДА &НомерДня > 0
					ТОГДА ВТ1.Дата > ВТ11.Дата
				ИНАЧЕ ВТ1.Дата < ВТ11.Дата
			КОНЕЦ)

СГРУППИРОВАТЬ ПО
	ВТ1.Дата,
	ВТ1.ВидДня
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВТ2.НомерДня КАК НомерДня,
	ВТ2.Дата,
	ВТ2.ВидДня
ИЗ
	ВТ2 КАК ВТ2
ГДЕ
	ВТ2.НомерДня = &НомерДня

УПОРЯДОЧИТЬ ПО
	НомерДня

Что фактически изменил:

- в соответствии с переданым значением номера дня от даты среза  считаются дни вперед или назад от текущей даты

- если номер дня  со знаком минус считеам назад и наоборот

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

И в заверешение прикрепляю функцию для определения искоемого дня в стандартном модуле для УПП.  (спасибо AnSk) 

// Функция возвращает дату отстоящую на заданное количество рабочих дней от начальной в соответствии с
//регламентированным производственным календарем
//
//Параметры:
// ДатаНач      - начальная дата
// ЧислоДней    - количество рабочих дней, на которое искомая дата должна отстоять от начальной
//
Функция ОпределитьДату(ДатаНач, ЧислоДней) Экспорт
	
	Запрос = Новый  Запрос;
	Запрос.УстановитьПараметр("ДатаНач",             ДатаНач);
	Запрос.УстановитьПараметр("ЧислоДней",           ЧислоДней);
	Запрос.УстановитьПараметр("РабочийДень",         Перечисления.ВидыДнейПроизводственногоКалендаря.Рабочий);
	Запрос.УстановитьПараметр("ПредпраздничныйДень", Перечисления.ВидыДнейПроизводственногоКалендаря.Предпраздничный);
	
	Если ЧислоДней > 0 Тогда
		Запрос.Текст = "
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ " + ЧислоДней + "
		|	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря
		|ИЗ
		|	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
		|ГДЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря > &ДатаНач
		|	 И (РегламентированныйПроизводственныйКалендарь.ВидДня = &РабочийДень
		|      ИЛИ РегламентированныйПроизводственныйКалендарь.ВидДня = &ПредпраздничныйДень)
		|УПОРЯДОЧИТЬ ПО 
		|	ДатаКалендаря ВОЗР";
		
	Иначе
		ЧислоДней = -ЧислоДней;
		
		Запрос.Текст = "
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ " + ЧислоДней + "
		|	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря
		|ИЗ
		|	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
		|ГДЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря < &ДатаНач
		|	 И (РегламентированныйПроизводственныйКалендарь.ВидДня = &РабочийДень
		|      ИЛИ РегламентированныйПроизводственныйКалендарь.ВидДня = &ПредпраздничныйДень)
        |УПОРЯДОЧИТЬ ПО
		|	ДатаКалендаря УБЫВ
		|";
		
	КонецЕсли;
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Выборка.Количество() = ЧислоДней Тогда
		Пока Выборка.Следующий() Цикл
			ТекДата = Выборка.ДатаКалендаря;
		КонецЦикла;
		Возврат ТекДата;
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

 

9

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. dandykry 3 29.11.18 11:07 Сейчас в теме
КалендарныеГрафики.ДатыБлижайшихРабочихДней(ПроизводственныйКалендарь, МассивДат, Ложь, Ложь, Истина);
JohnyDeath; triviumfan; SpartakM; rpgshnik; Mihaz1986; +5 Ответить
2. Mihaz1986 29.11.18 12:34 Сейчас в теме
(1)Всё уже написано за нас)
4. Mellow 13 29.11.18 13:23 Сейчас в теме
(2)на оригинальность не претендую возможно в других конфигурациях уже реализовано
3. Mellow 13 29.11.18 13:22 Сейчас в теме
(1)Ето для какой конфигурации, в упп нету такого
9. dandykry 3 29.11.18 14:22 Сейчас в теме
(3) А не вижу информации по поводу УПП. Написано для любой конфигурации (не правда)

http://prntscr.com/logwk3

мой код из БСП вроде бы
10. Mellow 13 29.11.18 15:01 Сейчас в теме
(9)Имеется ввиду что можна использовать для любой конфигурации в которой есть регламентировний производственний квлендарь, а тестировалось на упп и утп
11. dandykry 3 29.11.18 15:16 Сейчас в теме
(10) Ну в БСП производственных календарей может быть много) Не имеет значение. Хороший запрос
13. graf9190 30.11.18 15:54 Сейчас в теме
(9) В УПП нет, я делал так
Код
5. VmvLer 29.11.18 13:51 Сейчас в теме
то что автор дошел до решения сам - это да, почетно и похвально.

то что это наверняка реализовано в ЗУП - можно было догадаться.

Правда некоторые "профи" тут на меня часто вопят, мол, читать общие модули
современных конфигураций - это чушь, велосипедить - сила.)
rpgshnik; +1 Ответить
7. Mellow 13 29.11.18 14:08 Сейчас в теме
(5) В конфигурациях УПП и УТП такого общего модуля как КалендарныеГрафики нет . Именно с ними работал
6. Serg O. 155 29.11.18 14:02 Сейчас в теме
только БЕЗ выходных - вообще можно БЕЗ всяких регистров найти,
просто в цикле, используя только 1 функцию ДеньНедели (Дата1)
Определяет номер дня недели для указанной даты и если она < 6 то добавляем в результат.
а праздников - не так много в году - можно как доп.условие добавить по функции День(Дата1) - в году
Vlad_2008; +1 1 Ответить
8. Mellow 13 29.11.18 14:09 Сейчас в теме
(6) Как по мене запрос более универсальней
18. Vlad_2008 12 05.12.18 15:32 Сейчас в теме
(8) Устойчивое заблуждение, которое тянется с эпохи 7.7 и толстых клиентов.
Каждому способу свое применение, где-то запрос, где-то код и универсальность тут не причем.
Думать надо об оптимальности и учитывать что теперь у нас клиент-серверное взаимодействие.
Запрос - это сервер, а вот кодом можно решить задачу с использованием только клиентского вызова, т.е. в каждом случае выбираем способ исходя из условий задачи, а не из универсальности ... БСП вспомнил ... универсально аж о...ть ... при печати, не помню какого документа, видел стек вызовов в 40 пунктов - идиотизм, там же ... в типовых бесит запрос вида "ВЫБРАТЬ Ссылка ИЗ Документ.БлаБла ГДЕ Ссылка = &ТекущийДрокумент" ... на хрена здесь "универсальный" запрос, ссылка уже у нас "в руках". Очень часто вижу, когда разработчики используют запросы там, где достаточной простой выборки по объектам. Печалька ...
12. AnSk 30.11.18 13:23 Сейчас в теме
УТП, модуль ЗаполнениеДокументов

// Функция возвращает дату отстоящую на заданное количество рабочих дней от начальной в соответствии с
//регламентированным производственным календарем
//
//Параметры:
// ДатаНач      - начальная дата
// ЧислоДней    - количество рабочих дней, на которое искомая дата должна отстоять от начальной
//
Функция ОпределитьДату(ДатаНач, ЧислоДней) Экспорт
Показать


// Функция возвращает число рабочих дней между заданными датами по регламентированному производственному календарю
//
//Параметры:
// ДатаНач      - начальная дата
// ДатаКон      - конечная дата
//
Функция ЧислоРабочихДней(ДатаНач, ДатаКон) Экспорт
Показать
14. lunjio 50 03.12.18 14:52 Сейчас в теме
(12)
Надо ещё уточнить, что процедура прекрасно работает при поиске даты как в вперед, так и назад, при указании отрицательного числа, определяется соответствующая рабочая дата, а автора запрос работает только вперёд и никакого назад)
15. AnSk 03.12.18 18:54 Сейчас в теме
(14)
Главное задать направление поиска "несуществующих" процедур )
16. Mellow 13 03.12.18 19:11 Сейчас в теме
(12) В УТП даная функция считает количество рабочих дней между двумя датами, а не как в УПП возвращает дату отстоящую на заданное количество рабочих дней от начальной в соответствии с регламентированным производственным календарем
17. AnSk 04.12.18 09:51 Сейчас в теме
(16)
В сообщении описано две функции.
Оставьте свое сообщение