Разработка и Конфигурация · 11 мин
Как в запросе 1С выразить дату без времени
Как в запросе 1С отсечь время от даты: НАЧАЛОПЕРИОДА, ВЫРАЗИТЬ, ДАТАВРЕМЯ. Примеры кода, типичные ошибки, сравнение способов и ответы на вопросы.
В языке запросов 1С тип «Дата» всегда содержит и дату, и время с точностью до секунды. Это создаёт типичную проблему: при сравнении даты документа с параметром-периодом записи «теряются», потому что время документа (например, 14:35:12) не равно полуночи (00:00:00), которую задаёт пользователь. Чтобы корректно сравнивать, группировать и выводить даты, время нужно отсечь.
Существует несколько рабочих способов получить дату без времени прямо в запросе: функция НАЧАЛОПЕРИОДА, функция ДАТАВРЕМЯ с явным указанием компонентов и оператор ВЫРАЗИТЬ с квалификатором даты. У каждого подхода есть свои условия применения, ограничения по производительности и подводные камни, которые важно знать до изменения рабочего запроса.
Ниже разобраны все три способа с примерами кода, критериями выбора, проверкой результата и типичными ошибками, из-за которых отчёты показывают неполные данные.
Зачем отсекать время и когда это критично
Основной сценарий — сравнение дат в условии ГДЕ или в соединении таблиц. Документы почти всегда имеют время, отличное от полуночи. Если написать условие Документ.Дата = &Дата и передать параметр со значением 01.03.2026 00:00:00, то документ 01.03.2026 10:15:00 в выборку не попадёт. Пользователь видит «пустой» отчёт и считает, что данных нет, хотя они есть.
Вторая типовая задача — группировка по дням. Если сгруппировать продажи по полю Дата как есть, каждая секунда образует отдельную группу, и вместо строки «итог за день» получится сотня строк по одной секунде. Группировка по НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) сворачивает всё в сутки.
Третий сценарий — виртуальные таблицы регистров накопления и сведений. Параметры &НачалоПериода и &КонецПериода сравниваются с периодом записи с учётом времени, поэтому границы периода нужно задавать корректно: начало дня для стартовой даты и конец дня (или начало следующего дня) для конечной.
Способ 1: функция НАЧАЛОПЕРИОДА
Функция НАЧАЛОПЕРИОДА возвращает начало указанного периода для переданной даты. Для отсечения времени используется период ДЕНЬ: результатом будет та же календарная дата со временем 00:00:00.
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ) КАК ДатаБезВремени,
СУММА(Реализация.СуммаДокумента) КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ)
Тот же приём работает в условии отбора. Чтобы выбрать все документы за конкретный день независимо от времени, сравнивайте начало дня документа с параметром:
ГДЕ
НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ) = &НужнаяДата
Функция поддерживает и другие периоды: НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. Это удобно для агрегирования отчётов: НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) свернёт данные до первого числа месяца, что фактически даёт группировку по месяцам без дополнительных вычислений.
Способ 2: функция ДАТАВРЕМЯ с компонентами
Функция ДАТАВРЕМЯ собирает значение даты из числовых компонентов: год, месяц, день и необязательно часы, минуты, секунды. Если передавать только три первых аргумента, время результата будет 00:00:00 — это и есть дата без времени.
ВЫБРАТЬ
ДАТАВРЕМЯ(
ГОД(Реализация.Дата),
МЕСЯЦ(Реализация.Дата),
ДЕНЬ(Реализация.Дата)
) КАК ДатаБезВремени
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
Этот способ громоздче, чем НАЧАЛОПЕРИОДА, но даёт гибкость: можно сдвинуть месяц или год арифметикой прямо в аргументах, например ДАТАВРЕМЯ(ГОД(Дата), МЕСЯЦ(Дата) + 1, 1) для получения начала следующего месяца. Учтите, что выход за границы (месяц 13, день 32) может дать ошибку или неожиданный результат в зависимости от СУБД, поэтому арифметику с компонентами надо проверять на граничных датах — 31 декабря, 31 января.
ДАТАВРЕМЯ также используется для задания константных дат прямо в тексте запроса: ДАТАВРЕМЯ(2026, 1, 1) эквивалентно литералу 01.01.2026 00:00:00. Это удобно, когда параметр передавать нежелательно, а дата-константа нужна в условии.
Сравнение способов
Самый короткий и читаемый вариант для отсечения времени и группировки по дням. Ограничение: применение к полю в условии ГДЕ мешает использованию индекса.
Подходит, когда нужна арифметика с компонентами даты или константная дата в тексте запроса. Минус: громоздкая запись и риск ошибок на граничных датах.
Для отбора по периоду: Дата >= &НачалоДня И Дата <= &КонецДня, где границы вычислены на встроенном языке (НачалоДня, КонецДня). Сохраняет работу индекса, самый быстрый вариант на больших таблицах.
Способ 3: ВЫРАЗИТЬ — что он реально делает с датой
Оператор ВЫРАЗИТЬ часто ошибочно считают способом «обрезать» время. На практике ВЫРАЗИТЬ(Поле КАК ДАТА) лишь приводит значение к типу Дата, но не отсекает компонент времени: если в поле было 15.06.2026 18:22:40, то и после приведения останется то же значение.
Реальное назначение ВЫРАЗИТЬ с типом ДАТА — приведение полей составного типа (например, значений дополнительных реквизитов или характеристик) к типу Дата, чтобы дальше можно было применять функции работы с датами или сравнивать с параметром-датой. Пример:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(ВЫРАЗИТЬ(Свойства.Значение КАК ДАТА), ДЕНЬ) КАК ДатаБезВремени
ИЗ
Справочник.Номенклатура.ДополнительныеРеквизиты КАК Свойства
Правильный паттерн — комбинация: сначала ВЫРАЗИТЬ приводит составное значение к типу Дата, затем НАЧАЛОПЕРИОДА отсекает время. Использование одного только ВЫРАЗИТЬ для «очистки» времени — типовая ошибка, которая не даёт никакого эффекта, но и не вызывает ошибки выполнения, поэтому долго остаётся незамеченной.
Отбор по периоду: правильная схема с границами
Наиболее производительный и надёжный способ выбрать данные за период — не преобразовывать поле даты, а сравнивать его с заранее вычисленными границами. Границы готовятся на встроенном языке до выполнения запроса функциями НачалоДня() и КонецДня():
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания));
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
КонецДня() возвращает 23:59:59 указанной даты, поэтому условие МЕЖДУ корректно захватывает все документы последнего дня. Альтернатива — строгое неравенство Дата < ДОБАВИТЬКДАТЕ(&НачалоСледующегоДня, ...) или просто сравнение с началом следующего дня, вычисленным на встроенном языке: Дата >= &Начало И Дата < &СледующийДень. Такой вариант исключает двусмысленность с секундами.
Для виртуальных таблиц регистров накопления (Остатки, Обороты) параметр конца периода лучше передавать как объект Граница с видом «Включая», либо как конец дня — иначе движения, проведённые в последний день после 00:00:00, не попадут в остатки, и отчёт разойдётся с данными учёта.
- 1Определите задачу: группировка по дням, отбор за период или сравнение дат.
- 2Для группировки или вывода используйте НАЧАЛОПЕРИОДА(Поле, ДЕНЬ).
- 3Для отбора за период вычислите границы на встроенном языке (НачалоДня, КонецДня) и передайте их параметрами, не оборачивая поле даты в функцию.
- 4Если поле имеет составной тип, сначала приведите его через ВЫРАЗИТЬ(... КАК ДАТА), затем примените НАЧАЛОПЕРИОДА.
- 5Проверьте результат на документах с ненулевым временем и на граничных датах периода.
Проверка результата и контрольные точки
После изменения запроса проверьте его на заведомо проблемных данных. Создайте или найдите документ с временем, отличным от полуночи, — например, 14:37:25 — и убедитесь, что он попадает в выборку по своей дате. Затем проверьте границы периода: документы первого и последнего дня должны присутствовать в результате полностью.
Дополнительная проверка — сверка итогов. Сгруппируйте данные по НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) и сравните сумму по дню с итогом по необработанным записям за тот же день. Расхождение означает, что часть записей отфильтрована условием с ошибкой во времени.
Как проверить результат
Присутствует в выборке при отборе по этой дате
Отсутствует — условие сравнивает дату с полуночью без отсечения времени
Одна строка на каждый календарный день
Много строк внутри одного дня — группировка идёт по дате с временем
Совпадают с отчётом по регистру за тот же период
Не хватает движений последнего дня — граница задана как начало дня
Запрос отрабатывает за приемлемое время, план показывает поиск по индексу
Полное сканирование таблицы — функция применена к индексированному полю в условии
Частые вопросы
Можно ли получить дату без времени через ВЫРАЗИТЬ?
Нет. ВЫРАЗИТЬ(Поле КАК ДАТА) приводит значение к типу Дата, но компонент времени сохраняется. Для отсечения времени после приведения типа дополнительно примените НАЧАЛОПЕРИОДА(..., ДЕНЬ).
Чем НАЧАЛОПЕРИОДА отличается от КОНЕЦПЕРИОДА?
НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) возвращает 00:00:00 указанного дня, а КОНЕЦПЕРИОДА(Дата, ДЕНЬ) — 23:59:59. Первая функция используется для отсечения времени и задания левой границы периода, вторая — для правой границы при отборе за период включительно.
Как вывести дату без времени в отчёте на СКД?
В запросе набора данных вычислите поле через НАЧАЛОПЕРИОДА(Дата, ДЕНЬ). Если нужно только визуальное отображение без изменения данных, задайте для поля формат на закладке «Наборы данных» или в настройках: форматная строка вида ДФ=dd.MM.yyyy скроет время, оставив само значение нетронутым.
Почему условие Дата = &Дата не находит документы?
Потому что параметр обычно содержит полночь (00:00:00), а документы проведены в другое время. Замените условие на НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) = &Дата или на диапазон: Дата МЕЖДУ НачалоДня(&Дата) И КонецДня(&Дата) — второй вариант быстрее на больших таблицах.
Как получить дату без времени на встроенном языке, а не в запросе?
Используйте функцию НачалоДня(ЗначениеДаты) — она возвращает ту же дату со временем 00:00:00. Обратная функция КонецДня(ЗначениеДаты) возвращает 23:59:59 и применяется для правой границы периода.
Влияет ли отсечение времени на производительность запроса?
Да, если функция применяется к полю в условии ГДЕ или соединении: СУБД не может использовать индекс по этому полю и сканирует таблицу целиком. В списке выбранных полей и группировке влияние минимально. Для отборов предпочтительнее сравнивать само поле с параметрами-границами.
Что важно запомнить
Дата без времени в запросе 1С — это дата со временем 00:00:00, полученная через НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) или ДАТАВРЕМЯ с тремя компонентами. ВЫРАЗИТЬ время не отсекает, а только приводит тип. Для отбора за период используйте параметры-границы (НачалоДня/КонецДня) без функций над полем — это сохраняет работу индекса и не теряет документы с ненулевым временем.