Практический пример использования функций по работе с датам в запросе

В этой статье я хочу рассказать об одной реальной задаче, с которой столкнулся у клиента и о способе её решения. У клиента в программе есть справочник расписаний, где задается время движения определенного подвижного состава. Время задается в виде типа дата с видом даты – «Время». Т.е. вот так – ‘00010101235959’, это значит время 23:59:59 или так ‘0001010110010’ – 10.01.00. В справочнике есть время начала движения подвижного состава и время конца движения подвижного состава. Подвижной состав не может двигаться больше чем сутки, например, начнет в 10:00:00, закончит в 19:10:00. Но он может закончить ночью, уже следующим днем. Например, начало в 09:55:00, а конец в 01:05:00. Есть документа «Рабочая смена», который открывается и закрывается рано утром, по нему можно узнать к какому дню относится движение того или иного подвижного состава. Теперь задача – нужно по текущему времени узнать, должен ли подвижной состав двигаться по расписанию или зайти в парк. Например, по расписанию начало в 10:00:00, а конец в 19:00:00. Текущее время 15:12:23 – значит, еще должен двигаться. Текущее время 20:23:33 – уже должен быть в парке. Причем учесть, что текущее время может быть за полночь, т.е. в 01:10:23.

Сейчас я опишу свой алгоритм решения задачи, а потом покажу это все на запросе. По условиям задачи, у нас есть документ «Рабочая смена», из которого мы можем взять день рабочей смены. Нам нужно время расписания превратить в полную дату, т.е. день рабочей смены + время. Так же учесть, что время может быть за полночь, т.е. дата должна увеличиться на один день.

Например, день смены — 23.03.2017.
Начало расписания 1: 05:05:00 – преобразовать в 23.03.2017 05:05:00
Конец расписания 1: 19:53:00 – преобразовать в 23.03.2017 19:53:00
Нужно учесть, что конец может быть в следующий день
Начало расписания 1: 07:53:00 – преобразовать в 23.03.2017 07:53:00
Конец расписания 1: 01:10:00 – преобразовать в 24.03.2017 01:10:00 – увеличили дату на 1 день
И теперь мы можем спокойно проверять, входит ли наша дата в нужный промежуток.
И так начнем, я не буду создавать ни какие справочники расписаний у себя, просто создам запрос с разным набором дат, используя функцию языка запросов ДатаВремя

Теперь помещу её во временную таблицу и буду использовать.

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

ВЫБРАТЬ
втРасписания.НачалоРасписания,
втРасписания.КонецРасписания,
ДОБАВИТЬКДАТЕ(втРасписания.НачалоРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ)) КАК ДатаНачалаРасписания,
ДОБАВИТЬКДАТЕ(втРасписания.КонецРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ)) КАК ДатаКонцаРасписания
ИЗ
втРасписания КАК втРасписания
;


И рисунка вы видите, что дата после полуночи не совсем верная. Нужно что бы она сдвигалась на один день в плюс. Для этого будем использовать функцию ВЫБОР, и если время конца меньше времени начала, то в функции ДобавитьКДате, к параметру, который получился в результате разности дат добавлять единицу. Делать мы это будем применительно к полю ДатаКонцаРасписания

ВЫБРАТЬ
втРасписания.НачалоРасписания,
втРасписания.КонецРасписания,
ДОБАВИТЬКДАТЕ(втРасписания.НачалоРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ)) КАК ДатаНачалаРасписания,
ВЫБОР
КОГДА втРасписания.КонецРасписания < втРасписания.НачалоРасписания
ТОГДА ДОБАВИТЬКДАТЕ(втРасписания.КонецРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ) + 1)
ИНАЧЕ
ДОБАВИТЬКДАТЕ(втРасписания.КонецРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ))
КОНЕЦ КАК ДатаКонцаРасписания
ИЗ
втРасписания КАК втРасписания


И все теперь, уберем лишние поля, завернем это все во временную таблицу и в следующем запросе при помощи функции между будем проверять, входит ли текущая дата в этот период или нет.

ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(втРасписания.НачалоРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ)) КАК ДатаНачалаРасписания,
ВЫБОР
КОГДА втРасписания.КонецРасписания < втРасписания.НачалоРасписания
ТОГДА ДОБАВИТЬКДАТЕ(втРасписания.КонецРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ) + 1)
ИНАЧЕ
ДОБАВИТЬКДАТЕ(втРасписания.КонецРасписания, ДЕНЬ, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), НАЧАЛОПЕРИОДА(&ДатаСмены, ДЕНЬ), ДЕНЬ))
КОНЕЦ КАК ДатаКонцаРасписания
ПОМЕСТИТЬ втРасписанияСДатой
ИЗ
втРасписания КАК втРасписания
;

ВЫБРАТЬ
&ТекущаяДата
ВЫБОР
КОГДА &ТекущаяДата МЕЖДУ втРасписанияСДатой.ДатаНачалаРасписания И втРасписанияСДатой.ДатаКонцаРасписания
ТОГДА «Двигается по расписанию»
ИНАЧЕ «Должен закончить движение»
КОНЕЦ КАК Отметка,
втРасписанияСДатой.ДатаНачалаРасписания КАК ДатаНачалаРасписания,
втРасписанияСДатой.ДатаКонцаРасписания КАК ДатаКонцаРасписания
ИЗ
втРасписанияСДатой КАК втРасписанияСДатой


Всё! Задача решена.
Если Вы всё еще «плаваете» в конструкциях языка запросов, и у Вас вызывают трудности даже самые простые запросы, то рекомендую вам свой курс «Запросы в 1С для начинающих». Где эти и многие другие вопросы рассматриваются более подробно.

В чем особенность этого курса:
• Курс рассчитан на тех, кто не знаком с языком запросов в 1С;
• Учебный материал грамотно скомпонован и прост в освоении;
• Несколько десятков уроков;
• Полезные практические примеры;
• Все уроки изложены понятным и простым языком

Промо-код на скидку в 20%: hrW0rl9Nnx

Поддержите мой проект перечислив любую сумму

Вступайте в мои группы:

Вконтакте: https://vk.com/1c_prosto
Фейсбуке: https://www.facebook.com/groups/922972144448119/
ОК: http://ok.ru/group/52970839015518
Твиттер: https://twitter.com/signum2009

Добавить комментарий

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