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

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

Как программно сравнить даты в 1С

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

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

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

Как устроен тип «Дата» в 1С

Значение типа «Дата» во встроенном языке 1С всегда содержит и календарную дату, и время с точностью до секунды. Даже если вы видите в реквизите только «15.03.2026», внутри хранится «15.03.2026 0:00:00». Именно поэтому сравнение двух «одинаковых» дат может вернуть «Ложь»: у одной время 0:00:00, у другой — 14:23:47.

Литерал даты в коде записывается в апострофах в формате ГГГГММДД, при необходимости с добавлением времени: '20260315' или '20260315143000'. Альтернатива — функция Дата(2026, 3, 15). Пустое значение даты — это Дата(1, 1, 1), то есть 01.01.0001 0:00:00.

Базовые операторы сравнения дат

Для значений типа «Дата» работают все стандартные операторы сравнения: равно (=), не равно (<>), меньше, больше, меньше или равно, больше или равно. Сравнение выполняется с учётом времени: чем позже момент, тем «больше» дата.

Если Документ.ДатаОплаты < ТекущаяДата() Тогда

Сообщить("Срок оплаты истёк");

КонецЕсли;

Такой код корректен, когда сравниваются именно моменты времени. Проблема возникает, когда бизнес-смысл — «в пределах одного дня». Например, условие ДатаДокумента = ТекущаяДата() почти никогда не выполнится, потому что у текущей даты есть часы, минуты и секунды, а у даты документа обычно полночь.

Сравнение дат без учёта времени

Чтобы сравнить даты «по дню», оба значения приводят к началу дня функцией НачалоДня(). Она отсекает время, возвращая 0:00:00 указанной даты:

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

// Даты относятся к одному календарному дню

КонецЕсли;

Для проверки попадания момента в конкретный день удобна пара НачалоДня() и КонецДня(). Конец дня — это 23:59:59, поэтому условие «дата внутри дня» записывается как двойное сравнение:

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

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

// Момент попадает в указанный день

КонецЕсли;

Аналогично работают функции НачалоМесяца(), КонецМесяца(), НачалоКвартала(), КонецГода() — они позволяют сравнивать даты на уровне периода без ручного вычисления границ.

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

Пустая дата не равна NULL и не равна нулю — это вполне конкретное значение 01.01.0001. Поэтому проверка выглядит как сравнение с литералом или функцией:

Если Документ.ДатаОплаты = Дата(1, 1, 1) Тогда

// Дата оплаты не заполнена

КонецЕсли;

Если Документ.ДатаОплаты = '00010101' Тогда

// То же самое через литерал

КонецЕсли;

Обратный вариант — проверка на заполненность через неравенство: ДатаОплаты <> Дата(1,1,1). В запросах пустая дата сравнивается с ДАТАВРЕМЯ(1,1,1), а если реквизит составного типа и может содержать NULL, потребуется дополнительная проверка ЕСТЬ NULL или функция ЕСТЬNULL().

Типичные ошибки
01
Сравнение даты с пустой строкой или числом 0 вместо Дата(1,1,1) — условие никогда не выполнится
02
Сравнение «равно» с ТекущаяДата() без НачалоДня() — из-за времени условие почти всегда ложно
03
Использование КонецДня() при обмене с системами, где время точнее секунды — часть данных выпадает из выборки
04
Сравнение дат, приведённых к строке функцией Формат() — строковое сравнение не совпадает с хронологическим

Сравнение дат в запросах

В языке запросов 1С даты сравниваются теми же операторами, но параметры передаются как значения типа «Дата», а литералы записываются функцией ДАТАВРЕМЯ(год, месяц, день, часы, минуты, секунды). Типичный отбор за период выглядит так:

ВЫБРАТЬ

Реализация.Ссылка

ИЗ

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

ГДЕ

Реализация.Дата >= &НачалоПериода

И Реализация.Дата <= &КонецПериода

При установке параметров важно передать границы корректно: начало — через НачалоДня(НачалоПериода), конец — через КонецДня(КонецПериода). Иначе документы, проведённые в течение последнего дня периода после полуночи, не попадут в выборку.

Для виртуальных таблиц регистров (остатки, обороты) границы периода лучше передавать в параметры виртуальной таблицы, а не в секцию ГДЕ — это заметно снижает объём обрабатываемых данных и ускоряет запрос.

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

Арифметика дат и функции сдвига

К дате можно прибавлять и вычитать число — это секунды. Например, Дата + 86400 сдвигает момент на сутки вперёд. Разность двух дат тоже даёт число секунд, из которого вычисляют дни: (Дата2 - Дата1) / 86400. Результат может быть дробным, если время у дат разное.

Для сдвига на месяцы и годы простое прибавление секунд не подходит из-за разной длины месяцев. Используйте функцию ДобавитьМесяц(Дата, КоличествоМесяцев) — она корректно обрабатывает переходы через год и короткие месяцы. Для сравнения «сколько полных месяцев между датами» часто комбинируют РазностьДат() в запросах с единицей измерения МЕСЯЦ, ДЕНЬ или СЕКУНДА.

bsl
РазностьСекунд = ДатаОкончания - ДатаНачала;
РазностьДней = Цел((НачалоДня(ДатаОкончания) - НачалоДня(ДатаНачала)) / 86400);
ЧерезМесяц = ДобавитьМесяц(ТекущаяДата(), 1);

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

Чтобы убедиться, что сравнение работает как задумано, выведите обе даты с полным временем через Формат(Дата, "ДЛФ=DT") или смотрите значения в табло отладчика. Если время различается — значит, нужна нормализация через НачалоДня().

Полезный приём — тестирование на граничных значениях: документ ровно в 0:00:00, документ в 23:59:59 последнего дня периода, пустая дата, даты в разных месяцах и годах. Если логика устойчива на этих точках, она почти наверняка корректна для всех промежуточных значений.

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

Как проверить корректность сравнения

Документ в последний день периода
Норма

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

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

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

Сравнение дат одного дня
Норма

НачалоДня(Дата1) = НачалоДня(Дата2) возвращает Истина

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

Прямое сравнение дат возвращает Ложь из-за времени

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

Сравнение с Дата(1,1,1) возвращает Истина

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

Условие не срабатывает, проверка на пустоту не работает

FAQ

Чем отличается ТекущаяДата() от ТекущаяДатаСеанса()?

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

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

Приведите обе даты к началу месяца: НачалоМесяца(Дата1) = НачалоМесяца(Дата2). Для сравнения по году используйте функцию Год(Дата) и сравнивайте полученные числа.

Можно ли сравнивать даты, преобразованные в строку?

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

Как в запросе найти записи с незаполненной датой?

Используйте условие Реквизит = ДАТАВРЕМЯ(1,1,1). Если поле составного типа и может содержать NULL, добавьте проверку Реквизит ЕСТЬ NULL или объедините оба условия через ИЛИ.

Почему условие «Дата = КонецДня(Период)» не находит документ?

Потому что равенство требует совпадения до секунды: документ должен быть проведён ровно в 23:59:59. Для попадания в день используйте диапазон: Дата >= НачалоДня(Период) И Дата <= КонецДня(Период).

Итог

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

Дата в 1С всегда содержит время, поэтому для сравнения «по дню» применяйте НачалоДня() и КонецДня(). Пустая дата — это Дата(1,1,1), в запросах — ДАТАВРЕМЯ(1,1,1). Границы периодов передавайте в запрос уже нормализованными, а результат проверяйте на граничных значениях: полночь, 23:59:59 и пустая дата.