Работа с временными интервалами является одной из самых частых задач при написании запросов в платформе 1С:Предприятие 8. Разработчикам постоянно необходимо выбирать данные за сегодня, за текущий месяц или сравнивать конкретные метки времени с моментом выполнения отчета. Понимание того, как правильно оперировать этими значениями, критически важно для производительности и корректности выборки.
В языке запросов существует несколько встроенных функций и свойств, позволяющих динамически получать актуальное время. Однако новички часто совершают ошибки, пытаясь передать значения из внешней среды или используя неправильные методы усечения. В этой статье мы разберем все доступные способы получения текущей даты, их отличия и сферы применения в реальных конфигурациях.
Прежде чем углубляться в синтаксис, стоит отметить, что запрос выполняется на стороне сервера баз данных. Это означает, что использование клиентских переменных напрямую в тексте запроса невозможно без предварительной обработки. Система предоставляет специальные ключевые слова, которые интерпретируются движком запросов в момент их выполнения.
Использование свойства СЕГОДНЯ в языке запросов
Самым простым и распространенным способом получить текущую дату является использование встроенного свойства СЕГОДНЯ. Это свойство возвращает значение типа Дата, в котором время усечено до начала суток (00:00:00). Оно идеально подходит для сравнений, когда вам не важна точность до секунды, а важен именно календарный день.
При использовании СЕГОДНЯ в условии отбора, платформа автоматически подставляет актуальную дату сервера в момент запуска запроса. Это гарантирует, что отчет всегда будет формироваться по данным текущего дня, независимо от того, когда пользователь его откроет. Синтаксис предельно прост и не требует объявления дополнительных параметров.
Рассмотрим пример выборки документов, проведенных сегодня. Мы используем это свойство в конструкции ГДЕ для фильтрации записей. Обратите внимание, что сравнение идет с началом дня, поэтому для захвата всего дня часто требуется дополнительная логика или использование других функций.
ВЫБРАТЬ
РеализацияТоваровУслуг.Ссылка КАК Ссылка,
РеализацияТоваровУслуг.Дата КАК Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Дата >= СЕГОДНЯ
⚠️ Внимание: Свойство
СЕГОДНЯвозвращает дату с временем 00:00:00. Если вы используете условиеДата = СЕГОДНЯ, вы получите только документы, созданные ровно в полночь. Для выбора всех документов за день используйте диапазон или функциюКонецДня.
Важно понимать разницу между датой на клиенте и датой на сервере. В распределенных информационных базах или при работе через веб-клиент время может отличаться. Свойство СЕГОДНЯ всегда берет время сервера 1С, что обеспечивает консистентность данных при массовой обработке.
Используйте СЕГОДНЯ для отборов по регистраторам и документам, где точность до секунды не требуется, а важна принадлежность к календарному дню.
Функции усечения времени: НачалоДня и КонецДня
Часто возникает ситуация, когда необходимо выбрать данные не просто за "сегодня", а за конкретный временной интервал, ограниченный сутками. Для этих целей в языке запросов предусмотрены функции НАЧАЛОДНЯ и КОНЕЦДНЯ. Они позволяют гибко управлять границами периода, принимая в качестве аргумента любую дату или свойство времени.
Функция НАЧАЛОДНЯ возвращает дату с обнуленным временем, аналогично свойству СЕГОДНЯ, но может работать с произвольной датой. Функция КОНЕЦДНЯ возвращает дату с временем 23:59:59.999. Комбинация этих функций позволяет создать строгий диапазон для отбора данных за полные сутки.
Ниже приведен пример использования этих функций для формирования диапазона. Такой подход считается наиболее корректным с точки зрения оптимизации индексов базы данных, так как позволяет СУБД эффективно использовать индекс по полю даты.
- 📅 НАЧАЛОДНЯ(СЕГОДНЯ) — возвращает 00:00:00 текущей даты.
- ⏰ КОНЕЦДНЯ(СЕГОДНЯ) — возвращает 23:59:59 текущей даты.
- 🗓️ НАЧАЛОМЕСЯЦА(СЕГОДНЯ) — возвращает первый день текущего месяца.
При построении сложных отчетов часто требуется сравнивать периоды. Например, нужно найти документы, дата которых находится между началом текущего месяца и текущим моментом. В таком случае комбинация функций усечения становится незаменимым инструментом разработчика.
ГДЕ
Документ.Дата >= НАЧАЛОМЕСЯЦА(СЕГОДНЯ)
И Документ.Дата <= ТЕКУЩАЯДАТА()
Использование парных функций начала и конца периода позволяет создавать точные отборы, которые корректно работают с индексами СУБД и не пропускают записи на границах дней.
Работа с точным временем через ТЕКУЩАЯДАТА
В отличие от свойства СЕГОДНЯ, функция ТЕКУЩАЯДАТА() возвращает полную дату и время с точностью до миллисекунд. Это значение соответствует моменту запуска запроса на сервере. Использование этой функции необходимо в тех случаях, когда важна высокая точность фиксации событий.
Типичный сценарий использования ТЕКУЩАЯДАТА() — это регистрация времени начала выполнения тяжелой обработки или логирование событий в регистре сведений. Если вы запишете это значение в таблицу, вы сможете впоследствии проанализировать, сколько времени занял тот или иной процесс.
Однако стоит быть осторожным при использовании этой функции в условиях отбора ГДЕ. Поскольку время постоянно меняется, запрос с условием Дата < ТЕКУЩАЯДАТА() может вести себя непредсказуемо при долгом выполнении или повторных запусках в рамках одной транзакции.
⚠️ Внимание: Функция
ТЕКУЩАЯДАТА()вычисляется в момент компиляции дерева запроса. В длинных циклах или пакетной обработке это может привести к тому, что разные части выборки будут использовать немного разные временные метки.
Для сравнения интервалов с точностью до секунды часто применяют вычитание интервала из текущего времени. Например, чтобы найти документы за последний час, можно использовать конструкцию с функцией ДОБАВИТЬКДАТЕ, отнимая один час от текущего момента.
Разработчики часто путают ТЕКУЩАЯДАТА и СЕГОДНЯ. Запомните простое правило: если вам нужно "сегодняшнее число" для отчета по продажам — берите СЕГОДНЯ. Если нужно зафиксировать точный момент обновления записи в базе — используйте ТЕКУЩАЯДАТА.
Передача даты через параметры запроса
В прикладных задачах часто возникает необходимость передать дату из интерфейса программы внутрь запроса. Это реализуется через механизм параметров. В коде 1С вы создаете объект Запрос, устанавливаете значение параметра и затем выполняете выборку. Это дает максимальную гибкость.
Преимущество такого подхода заключается в возможности многократного использования одного и того же текста запроса с разными датами без его перекомпиляции. Вы можете один раз написать запрос с параметром &ДатаНач, а затем вызывать его для разных периодов, просто меняя значение параметра в коде.
Пример установки параметра в коде модуля объекта или формы выглядит следующим образом. Мы берем текущую дату функцией ТекущаяДата() языка 1С и присваиваем её параметру запроса.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ... ГДЕ Дата >= &НачалоПериода";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата()));
Результат = Запрос.Выполнить();
При использовании параметров важно следить за типами данных. Если в запросе ожидается Дата, а вы передадите Строку, система попытается выполнить приведение типов, что может привести к ошибке выполнения или некорректному отбору. Явное указание типа в коде — хорошая практика.
☑️ Проверка параметров запроса
Сравнение методов и производительность
Выбор способа указания даты напрямую влияет на скорость выполнения запроса, особенно в больших информационных базах с миллионами записей. Понимание того, как СУБД обрабатывает различные функции в условии ГДЕ, помогает писать оптимизированный код.
Использование констант и свойств уровня сервера (как СЕГОДНЯ) обычно является наиболее эффективным вариантом. База данных может заранее построить план выполнения, зная конкретные границы выборки. В то же время, вызов функций над полями таблицы может привести к полному сканированию таблицы (Full Table Scan).
В таблице ниже приведено сравнение основных методов работы с датой в запросах 1С с точки зрения их назначения и особенностей использования.
| Метод | Точность | Особенности | Рекомендуемое использование |
|---|---|---|---|
СЕГОДНЯ |
До дня | Всегда 00:00:00 | Отборы по документам за сутки |
ТЕКУЩАЯДАТА() |
До мс | Динамическое время | Логирование, таймстампы |
НАЧАЛОДНЯ() |
До дня | Усекает любую дату | Нормализация дат для группировки |
| Параметр | Любая | Задается из кода | Отчеты с выбором периода пользователем |
Одной из частых ошибок является наложение функций на поле таблицы в условии отбора. Конструкция вида ГДЕ НАЧАЛОДНЯ(Таблица.Дата) = СЕГОДНЯ заставляет базу данных вычислять функцию для каждой строки таблицы, что убивает производительность индексов. Правильно писать ГДЕ Таблица.Дата >= СЕГОДНЯ И Таблица.Дата < ДОБАВИТЬКДАТЕ(СЕГОДНЯ, 1, ДЕНЬ).
⚠️ Внимание: Никогда не применяйте функции преобразования даты к полям таблицы в левой части условия сравнения. Это делает условие неоптимизируемым и приводит к резкому падению скорости работы в больших базах данных.
Почему индексы не работают с функциями?
Индексы в базах данных (SQL) строятся по значениям полей. Когда вы применяете функцию к полю (например, Год(Дата)), СУБД не может использовать индекс, так как значения в индексе не совпадают с результатом функции. Ей приходится перебирать все записи подряд.
Особенности работы в разных режимах и расписаниях
При автоматической обработке данных, например, в регламентных заданиях или внешних обработках, понятие "текущая дата" может иметь нюансы. Регламентное задание может быть запущено в 23:59, а завершиться уже после полуночи. В таких случаях использование СЕГОДНЯ внутри долгого запроса может привести к логическим разрывам данных.
Если вы разрабатываете механизм, который должен работать стабильно независимо от времени суток, рекомендуется фиксировать дату начала работы в переменной и передавать её во все вложенные запросы как параметр. Это обеспечит консистентность выборки в рамках одной сессии обработки.
Также стоит учитывать часовой пояс сервера. В облачных решениях или при размещении базы данных в другом регионе время сервера 1С может отличаться от времени пользователя. Для корректной работы с датами в таких случаях необходимо приводить время к единому стандарту или использовать функции конвертации, если конфигурация поддерживает многовариантный учет времени.
В заключение, правильный выбор метода работы с датой зависит от конкретной задачи. Для отчетов пользователю — СЕГОДНЯ и параметры. Для системного логирования — ТЕКУЩАЯДАТА. Главное — избегать функций над полями в условиях отбора для сохранения высокой производительности системы.
Фиксация даты в параметре перед циклом обработки гарантирует, что все операции в рамках одного сеанса будут использовать единую временную метку, избегая проблем с переходом через полночь.
Часто задаваемые вопросы (FAQ)
Как получить вчерашнюю дату в запросе 1С?
Для получения вчерашней даты используйте функцию ДОБАВИТЬКДАТЕ. Пример: ДОБАВИТЬКДАТЕ(СЕГОДНЯ, -1, ДЕНЬ). Это вернет дату вчера с временем 00:00:00.
Можно ли использовать дату из формы отчета в запросе?
Да, это стандартная практика. Значение из поля формы (например, ЭлементыФормы.Период.Значение) необходимо передать в запрос через метод УстановитьПараметр, связав с именем параметра в тексте запроса.
В чем разница между СЕГОДНЯ и ТекущаяДата() в коде?
В коде 1С ТекущаяДата() возвращает полное время. В тексте запроса СЕГОДНЯ — это спецсвойство, возвращающее усеченную дату. Аналогом ТекущаяДата() внутри запроса является функция ТЕКУЩАЯДАТА().
Почему запрос не находит документы, созданные сегодня?
Скорее всего, вы используете условие равенства Дата = СЕГОДНЯ. Так как СЕГОДНЯ это 00:00:00, а документы создаются в другое время, равенство не выполняется. Используйте диапазон: Дата >= СЕГОДНЯ.