К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как получить начало дня в запросе 1С

Как получить начало дня в запросе 1С через НАЧАЛОПЕРИОДА, отбор документов за день, работа с границами периода, типовые ошибки и проверка результата.

Получить начало дня в запросе 1С чаще всего требуется при отборе документов за конкретную дату, построении отчётов по дням и сравнении дат без учёта времени. В языке запросов для этого существует встроенная функция НАЧАЛОПЕРИОДА, которая приводит любую дату со временем к полуночи указанного дня — 00:00:00.

Задача возникает потому, что тип «Дата» в 1С всегда содержит время с точностью до секунды. Документ, проведённый в 14:35:12, не равен дате «01.03.0001 00:00:00», и прямое сравнение Дата = &Дата без приведения к началу дня даст ложный результат. Поэтому безопасный подход — либо приводить значение к началу периода функцией, либо сравнивать через интервал «начало дня — конец дня».

Ниже разобраны синтаксис функции, практические сценарии отбора за день, альтернативы через параметры-границы, работа в СКД, а также типичные ошибки и способы проверить корректность результата.

Функция НАЧАЛОПЕРИОДА: синтаксис и принцип работы

Функция имеет два параметра: дата (или выражение даты) и тип периода. Для начала дня вторым параметром указывается ключевое слово ДЕНЬ:

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(&ДатаСоВременем, ДЕНЬ) КАК НачалоДня

Если передать в параметр &ДатаСоВременем значение 15.06.2026 18:42:07, функция вернёт 15.06.2026 00:00:00. Аналогично работают другие типы периода: НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД — функция универсальна и применяется для любых периодических отборов.

Важно понимать: функция выполняется на сервере СУБД при каждом вызове. Если она применяется к полю таблицы в условии ГДЕ, индекс по полю даты использоваться не будет, и на больших таблицах запрос может заметно замедлиться. Это ключевое ограничение, которое определяет выбор между двумя основными приёмами.

Отбор документов за один день

Самый частый сценарий — выбрать все документы, проведённые в течение конкретной даты, независимо от времени. Первый способ — приведение поля даты к началу дня и сравнение с параметром:

ВЫБРАТЬ

РеализацияТоваровУслуг.Ссылка,

РеализацияТоваровУслуг.Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

ГДЕ

НАЧАЛОПЕРИОДА(РеализацияТоваровУслуг.Дата, ДЕНЬ) = &НужнаяДата

Параметр &НужнаяДата при этом можно передавать с любым временем — функция сравнивает уже приведённое значение, но сам параметр тоже стоит передавать как начало дня для однозначности: НачалоДня(ТекущаяДатаСеанса()) в коде модуля.

Этот вариант прост и читаем, но не использует индекс по полю «Дата». На таблицах с сотнями тысяч документов выборка может выполняться полным сканированием.

Производительный вариант через интервал

Более быстрый приём — сравнивать само поле даты с двумя параметрами-границами, вычисленными заранее в коде:

Запрос.УстановитьПараметр("НачалоДня", НачалоДня(ДатаОтбора));

Запрос.УстановитьПараметр("КонецДня", КонецДня(ДатаОтбора));

ГДЕ

РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоДня И &КонецДня

Здесь функции НачалоДня() и КонецДня() — это методы встроенного языка (не языка запросов), они вычисляются один раз до выполнения запроса. СУБД использует индекс по полю «Дата», и выборка выполняется быстро даже на больших объёмах.

Два способа отбора за день

НАЧАЛОПЕРИОДА в условии ГДЕ

Короткая запись, параметр один. Минус: не используется индекс по дате, на больших таблицах медленнее.

Интервал МЕЖДУ &НачалоДня И &КонецДня

Два параметра вычисляются в коде. Индекс работает, запрос быстрый. Рекомендуется для больших таблиц.

Начало дня для текущей даты и динамических отборов

Когда начало дня нужно не для параметра, а для «сегодня», в языке запросов доступна функция &ТекущаяДата через параметр либо конструкция с ТекущаяДатаСеанса() в коде. Прямой функции «текущая дата» в языке запросов нет — значение передаётся параметром:

Запрос.УстановитьПараметр("НачалоТекущегоДня", НачалоДня(ТекущаяДатаСеанса()));

Использовать ТекущаяДата() в серверном коде не рекомендуется: она возвращает время клиентского компьютера, которое может отличаться от серверного. ТекущаяДатаСеанса() гарантирует единое серверное время и корректную работу в распределённых системах с разными часовыми поясами.

Если отчёт строится за «последние N дней», начало периода вычисляют арифметикой дат: НачалоДня(ТекущаяДатаСеанса()) - (N - 1) * 86400, где 86400 — число секунд в сутках. В самом языке запросов для сдвига дат есть функция ДОБАВИТЬКДАТЕ(&Дата, ДЕНЬ, -7).

Начало дня в СКД и динамических списках

В системе компоновки данных функция НАЧАЛОПЕРИОДА используется так же, но параметры периода обычно оформляются как стандартный период. Типовой приём — выражение в параметрах виртуальной таблицы или в отборе:

ГДЕ

Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода

Для группировки данных по дням в отчёте поле периода приводят к началу дня, чтобы все записи внутри суток попали в одну группу:

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(ПродажиОбороты.Период, ДЕНЬ) КАК День,

СУММА(ПродажиОбороты.СуммаОборот) КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты(, , День, ) КАК ПродажиОбороты

СГРУППИРОВАТЬ ПО

НАЧАЛОПЕРИОДА(ПродажиОбороты.Период, ДЕНЬ)

Заметим, что у виртуальных таблиц оборотов периодичность «День» уже возвращает дату в начале дня, поэтому дополнительное приведение там избыточно — оно нужно при выборке из физических таблиц документов и регистров с произвольным временем.

Динамические списки

В динамическом списке произвольного запроса отбор «за сегодня» задаётся через параметр с выражением НачалоДня(ТекущаяДатаСеанса()) в обработчике ПриПолученииДанныхНаСервере или при создании формы. Задавать вычисляемое выражение прямо в тексте запроса списка нельзя — только через параметры.

Порядок действий для отбора за день
  1. 1
    Определите, откуда берётся дата отбора: параметр, текущая дата сеанса или поле формы
  2. 2
    В коде вычислите границы: НачалоДня(Дата) и КонецДня(Дата)
  3. 3
    Передайте оба значения параметрами в запрос
  4. 4
    В тексте запроса используйте условие Дата МЕЖДУ &НачалоДня И &КонецДня
  5. 5
    Выполните запрос и проверьте, что попали документы с разным временем внутри дня

Частые ошибки и как их избежать

Первая ошибка — сравнение даты документа с параметром через равенство без приведения: Документ.Дата = &Дата. Поскольку у документа почти всегда есть время, а параметр передан как начало дня, условие не выполнится ни для одной записи. Запрос вернёт пустой результат без какой-либо ошибки, что затрудняет диагностику.

Вторая ошибка — использование КОНЕЦПЕРИОДА(&Дата, ДЕНЬ) там, где граница должна быть включительной. Функция возвращает 23:59:59, и документ с датой-временем, попадающей в последнюю секунду, обычно учитывается корректно, но при работе с границами моментов времени в регистрах поведение отличается. Для надёжности в отборах по документам используйте пару «начало дня — конец дня» через МЕЖДУ.

Третья ошибка — применение НАЧАЛОПЕРИОДА к полю в условии соединения таблиц или в ГДЕ на больших регистрах. Это отключает индексы и приводит к таймаутам. Выносите вычисление границ в параметры, а функцию применяйте только к параметрам и в секции ВЫБРАТЬ для группировок.

Типичные ошибки
01
Сравнение Дата = &Дата без приведения — запрос молча возвращает пустой результат
02
НАЧАЛОПЕРИОДА вокруг поля таблицы в условии ГДЕ — теряется индекс, запрос тормозит
03
Использование ТекущаяДата() вместо ТекущаяДатаСеанса() — расхождение времени клиента и сервера
04
Сравнение с концом дня через < вместо МЕЖДУ — теряются документы последней секунды

Проверка результата и отладка

Убедиться, что начало дня вычислено правильно, проще всего через консоль запросов: выполните запрос ВЫБРАТЬ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) с тестовым параметром и проверьте, что результат — 00:00:00 нужной даты. Затем выполните основной запрос и сверьте, что в выборку попали документы с временем 00:05, 12:30 и 23:50 одного дня.

Дополнительная проверка — сравнить количество записей при отборе через НАЧАЛОПЕРИОДА и через интервал МЕЖДУ. Результаты должны совпадать. Если через интервал записей больше, где-то в данных встречаются даты за пределами ожидаемого диапазона или проблема в часовых поясах при загрузке данных из внешних систем.

При работе с сеансовыми датами в распределённых базах проверьте настройку часового пояса информационной базы: документ, введённый в другом поясе, может попасть «не в тот» день относительно серверного времени.

Контрольные точки

Как проверить результат

Значение НАЧАЛОПЕРИОДА в консоли запросов
Норма

Возвращается 00:00:00 нужной даты

Тревожный признак

Время отлично от полуночи или дата смещена

Состав выборки за день
Норма

Есть документы с любым временем внутри суток

Тревожный признак

Попадают только документы с 00:00:00 или выборка пуста

Скорость выполнения на большой таблице
Норма

Запрос с МЕЖДУ выполняется быстро

Тревожный признак

Долгое выполнение — функция применена к полю в ГДЕ

FAQ

Чем НАЧАЛОПЕРИОДА отличается от функции НачалоДня() в коде?

НАЧАЛОПЕРИОДА — функция языка запросов, выполняется внутри запроса на СУБД. НачалоДня() — метод встроенного языка, вычисляется в коде до выполнения запроса, и результат передаётся параметром. Оба дают 00:00:00, но параметр позволяет использовать индексы.

Можно ли получить начало дня без функции, вычитанием времени?

Технически можно комбинацией ДОБАВИТЬКДАТЕ и извлечения частей даты, но это громоздко и нечитаемо. НАЧАЛОПЕРИОДА — штатный и самый понятный способ, альтернативы оправданы только в экзотических сценариях.

Почему запрос с НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) = &Дата работает медленно?

Функция применена к полю таблицы, поэтому СУБД не может использовать индекс по дате и сканирует всю таблицу. Перепишите условие как Дата МЕЖДУ &НачалоДня И &КонецДня, вычислив параметры в коде.

Как получить начало дня для даты в произвольном часовом поясе?

Язык запросов работает с датами как с абсолютными значениями без учёта поясов. Если данные приходят из разных поясов, приводите их к единому поясу базы в коде перед передачей параметром, иначе границы дня будут смещены.

Что вернёт НАЧАЛОПЕРИОДА для пустой даты?

Для пустой даты (01.01.0001 00:00:00) функция вернёт ту же пустую дату. Если поле может быть пустым, добавьте проверку, иначе такие записи попадут в группу с минимальной датой при группировке.

Как сгруппировать обороты регистра по дням?

Используйте виртуальную таблицу оборотов с периодичностью «День» — поле Период уже будет в начале дня. Если данные берутся из физической таблицы, группируйте по НАЧАЛОПЕРИОДА(Период, ДЕНЬ).

Итог

Что важно запомнить

Начало дня в запросе 1С — это НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ), результат 00:00:00. Для отборов на больших таблицах вычисляйте НачалоДня() и КонецДня() в коде и сравнивайте поле даты через МЕЖДУ — так работает индекс. Текущую дату передавайте параметром через ТекущаяДатаСеанса().