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

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

1С: как сравнить даты без учёта времени

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

В 1С значение типа «Дата» всегда содержит и дату, и время с точностью до секунды. Поэтому прямое сравнение Дата1 = Дата2 часто даёт ложный результат: документы за один календарный день, но введённые в 09:15 и 18:42, платформа считает разными. Для отчётов, отборов и проверок периодов нужно сравнивать именно календарные дни, отбрасывая время.

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

Ниже разобраны все основные способы с примерами кода, указаны ограничения каждого подхода и типичные ошибки, из-за которых сравнение дат «не работает».

Почему прямое сравнение дат в 1С не работает

Тип «Дата» в платформе 1С хранит момент времени: год, месяц, день, часы, минуты и секунды. Когда пользователь вводит дату документа, платформа обычно подставляет текущее время. Даже если на форме видно только «12.03.2026», внутри значение может быть «12.03.2026 14:37:02».

Следствие — условие Если Документ.Дата = '20260312' Тогда почти никогда не сработает, потому что литерал '20260312' означает полночь (00:00:00), а дата документа содержит реальное время. Это одна из самых частых причин «непонятного» поведения отборов и проверок у начинающих разработчиков.

Отдельная ловушка — пустая дата. Значение '00010101' тоже является датой с нулевым временем, и сравнение с ней по дню без предварительной проверки на заполненность может дать неожиданные результаты.

Способ 1. Сравнение через НачалоДня() в коде

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

Если НачалоДня(Дата1) = НачалоДня(Дата2) Тогда

// даты попадают на один календарный день

КонецЕсли;

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

Если НачалоДня(ДатаОтгрузки) < НачалоДня(ДатаЗаказа) Тогда

Сообщить("Отгрузка не может быть раньше дня заказа");

КонецЕсли;

Проверка попадания даты в конкретный день удобно записывается через диапазон от начала до конца дня — так не нужно вызывать функцию дважды с обеих сторон:

Если ПроверяемаяДата >= НачалоДня(ЦелевойДень)

И ПроверяемаяДата <= КонецДня(ЦелевойДень) Тогда

// дата внутри нужного дня

КонецЕсли;

Способ 2. Сравнение дат в запросе

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

ВЫБРАТЬ

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

ИЗ

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

ГДЕ

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

Параметр &День при этом должен содержать начало дня: Запрос.УстановитьПараметр("День", НачалоДня(НужнаяДата));. Альтернатива — передать одну дату и сравнивать с диапазоном:

ГДЕ

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

Здесь параметры задаются как НачалоДня(Период) и КонецДня(Период) на стороне кода. Важный нюанс: в условии МЕЖДУ границы включаются, поэтому документ ровно в 23:59:59 попадёт в выборку.

Сравнение в СКД и динамических списках

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

bsl
Запрос = Новый Запрос("ВЫБРАТЬ Т.Ссылка ИЗ Документ.РеализацияТоваровУслуг КАК Т ГДЕ Т.Дата МЕЖДУ &Начало И &Конец");
Запрос.УстановитьПараметр("Начало", НачалоДня(НужнаяДата));
Запрос.УстановитьПараметр("Конец", КонецДня(НужнаяДата));

Способ 3. Сравнение через строку и через разность дат

Иногда дату удобно сравнить как строку. Функция Формат() с форматной строкой «ДЛФ=D» отбрасывает время:

Если Формат(Дата1, "ДЛФ=D") = Формат(Дата2, "ДЛФ=D") Тогда

// один календарный день

КонецЕсли;

Способ рабочий, но медленнее сравнения дат и зависит от региональных настроек: при переносе кода в базу с другой локалью формат может отличаться, хотя на равенство двух значений в одном сеансе это не влияет. Использовать строковое сравнение стоит только там, где нужен именно текст — например, при группировке в свёртке таблицы значений.

Ещё один вариант — сравнение количества дней между датами без привязки к началу суток:

РазностьДней = (НачалоДня(Дата2) - НачалоДня(Дата1)) / 86400;

Здесь 86400 — число секунд в сутках. Результат показывает разницу в календарных днях и удобен для проверок вида «между датами не более 3 дней».

Сравнение способов

НачалоДня() в коде

Универсальный и быстрый вариант для модулей. Ограничений практически нет.

НАЧАЛОПЕРИОДА в запросе

Правильный выбор для запросов и СКД. Требует аккуратности с параметрами и границами периода.

Формат() в строку

Подходит для группировок и отображения. Медленнее и зависит от форматных настроек.

Разность в секундах

Удобен для проверок интервалов в днях. Требует приведения к началу дня, иначе результат дробный.

Сравнение текущей даты с датой документа

Частая задача — проверить, что документ оформлен «сегодня». Здесь Дата) = НачалоДня(ТекущаяДата()) Тогда

// документ сегодняшний

КонецЕсли;

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

Типичные ошибки и как их проверить

Первая ошибка — сравнение даты с литералом без времени: Документ.Дата = '20260312'. Литерал означает полночь, и условие сработает только для документов, проведённых ровно в 00:00:00. Правильно — НачалоДня(Документ.Дата) = '20260312'.

Вторая ошибка — использование КонецДня() в параметрах запроса с виртуальными таблицами регистров. Для остатков и оборотов период задаётся границей, и неправильная граница (включая/исключая точку) меняет результат. Проверяйте, что граница периода задана осознанно.

Третья ошибка — сравнение дат, одна из которых не заполнена. Пустая дата 01.01.0001 00:00:00 пройдёт любую проверку «меньше», что приведёт к ложным срабатываниям. Перед сравнением добавляйте ЗначениеЗаполнено(Дата).

Типичные ошибки
01
Сравнение Дата = '20260312' без НачалоДня — условие не срабатывает из-за времени в дате документа.
02
Использование ТекущаяДата() на сервере вместо ТекущаяДатаСеанса() — сдвиг дня для удалённых пользователей.
03
Сравнение без проверки ЗначениеЗаполнено — пустая дата проходит проверки «меньше» и ломает логику.
04
Отбор «Дата равно» в динамическом списке — пользователь видит пустой список, хотя документы за день есть.

Как проверить, что сравнение работает правильно

Быстрый способ убедиться в корректности — вывести оба сравниваемых значения с полным временем через Сообщить() или посмотреть их в отладчике в формате «Дата и время». Если время отличается, а сравнение должно трактовать даты как равные — значит, приведение к началу дня отсутствует.

Для запросов полезна проверка на контрольном примере: создайте два документа за один день с разным временем (например, 08:00 и 22:30) и убедитесь, что запрос с НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) возвращает оба, а отбор по диапазону «НачалоДня–КонецДня» — тоже оба, включая документ в 23:59.

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

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

Два значения за один день с разным временем
Норма

Сравнение через НачалоДня возвращает Истина

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

Сравнение возвращает Ложь — приведение к дню отсутствует

Запрос с параметром-днём
Норма

Выбираются все документы дня от 00:00 до 23:59

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

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

Пустая дата в сравнении
Норма

Отдельная ветка логики через ЗначениеЗаполнено

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

Пустая дата участвует в сравнении наравне с заполненными

Часто задаваемые вопросы

Чем НачалоДня отличается от КонецДня?

НачалоДня возвращает ту же дату со временем 00:00:00, КонецДня — со временем 23:59:59. Вместе они задают границы календарного дня, что удобно для проверок вхождения и параметров запросов.

Можно ли сравнить даты без времени в запросе без НАЧАЛОПЕРИОДА?

Да, через условие МЕЖДУ с параметрами НачалоДня(Период) и КонецДня(Период), заданными в коде. Это часто быстрее, чем применять функцию к полю, потому что не мешает использованию индекса по дате.

Почему отбор «Дата = 12.03.2026» в динамическом списке ничего не находит?

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

Как сравнить только месяц и год двух дат?

Приведите обе даты к началу месяца: НачалоМесяца(Дата1) = НачалоМесяца(Дата2) в коде или НАЧАЛОПЕРИОДА(Поле, МЕСЯЦ) в запросе. Тот же приём работает для квартала, недели и года.

Влияет ли часовой пояс на сравнение дат?

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

Что быстрее: НачалоДня или сравнение строк через Формат?

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

Итог

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

Дата в 1С всегда содержит время, поэтому сравнивайте календарные дни через НачалоДня() в коде и НАЧАЛОПЕРИОДА(Поле, ДЕНЬ) в запросах. Для диапазонов используйте пару НачалоДня/КонецДня, проверяйте заполненность дат и учитывайте часовой пояс сеанса.