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

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

Как сравнивать даты в 1С

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

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

Главная особенность типа «Дата» в 1С — он всегда содержит и дату, и время с точностью до секунды. Поэтому сравнение Дата1 = Дата2 сработает только при полном совпадении до секунды, а проверка «попадает ли документ в сегодняшний день» требует приведения значений к границам дня. Игнорирование этого правила — самая частая причина «неработающих» условий.

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

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

Значения типа «Дата» поддерживают полный набор операторов сравнения: =, <>, <, >, <=, >=. Сравнение выполняется хронологически: более ранняя дата считается меньшей. Результат операции — булево значение, которое можно использовать в условиях, циклах и присваиваниях.

Если Документ.Дата > ТекущаяДатаСеанса() Тогда

Сообщить("Дата документа в будущем");

КонецЕсли;

Если СрокДействияДоговора <= ТекущаяДатаСеанса() Тогда

Сообщить("Договор истёк или истекает сегодня");

КонецЕсли;

Обратите внимание на разницу между строгим и нестрогим сравнением. Условие Срок < ТекущаяДата не сработает в момент, когда срок равен текущей дате с точностью до секунды. Если «последний день» должен считаться ещё действующим, используйте <= с приведением к концу дня: ТекущаяДатаСеанса() <= КонецДня(Срок).

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

Учёт времени: НачалоДня, КонецДня и сравнение по дню

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

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

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

КонецЕсли;

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

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

И ДатаПроверки <= КонецДня(НужнаяДата) Тогда

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

КонецЕсли;

Аналогично работают функции НачалоМесяца(), КонецМесяца(), НачалоКвартала(), НачалоНедели() и другие — они нужны, когда сравнение выполняется по периоду, а не по конкретному моменту. Для сдвига дат при сравнении используйте ДобавитьКДате(): например, проверка «истекает ли срок в ближайшие 7 дней» выглядит как Срок <= ДобавитьКДате(ТекущаяДатаСеанса(), "День", 7).

Сравнение с пустой датой и проверка заполненности

Пустая дата в 1С — это значение 01.01.0001 00:00:00. Её можно задать литералом '00010101' или получить как значение по умолчанию незаполненного реквизита. Прямое сравнение с пустой датой — рабочий способ проверки: Если Реквизит.ДатаОкончания = '00010101' Тогда.

Более универсальный вариант — функция ЗначениеЗаполнено(). Она возвращает Ложь для пустой даты, пустой строки, нуля, Неопределено и пустых ссылок, поэтому подходит для проверки реквизитов любого типа:

Если ЗначениеЗаполнено(Договор.ДатаОкончания) Тогда

// Срок задан, можно сравнивать с текущей датой

Иначе

// Договор бессрочный

КонецЕсли;

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

Типичные ошибки
01
Сравнение дат оператором = без приведения к началу дня — условие не срабатывает из-за разного времени внутри дат
02
Сравнение с пустой датой без проверки ЗначениеЗаполнено() — бессрочные договоры ошибочно считаются просроченными
03
Сравнение даты со строкой вида "01.01.2026" — строка не приводится к дате автоматически, условие ведёт себя непредсказуемо
04
Использование ТекущаяДата() вместо ТекущаяДатаСеанса() на сервере — в клиент-серверном режиме возможны расхождения часовых поясов

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

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

ВЫБРАТЬ

Док.Ссылка

ИЗ

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

ГДЕ

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

И Док.ДатаОплаты <> ДАТАВРЕМЯ(1,1,1)

Оператор МЕЖДУ включает обе границы, поэтому параметр конца периода обычно передают как КонецДня(Период) — иначе документы последнего дня с ненулевым временем выпадут из выборки. Это одна из самых частых причин «неполных» отчётов.

В запросе доступны функции работы с датами: НАЧАЛОПЕРИОДА(Дата, ДЕНЬ), КОНЕЦПЕРИОДА(Дата, МЕСЯЦ), ДОБАВИТЬКДАТЕ(), РАЗНОСТЬДАТ(). Последняя удобна для сравнения по разнице: например, отобрать документы, где между датой отгрузки и оплатой прошло больше 30 дней.

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

Сравнение дат в СКД, отборах и на форме

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

При программной установке отбора динамического списка или таблицы значений используйте вид сравнения из перечисления ВидСравненияКомпоновкиДанных — «Равно», «БольшеИлиРавно», «ВИнтервалеВключаяГраницы» и другие. Установка отбора «Равно» по дате с временем снова упирается в проблему секунд: для списка документов за день ставьте интервал, а не точное равенство.

Маршрут решения

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

Нужно сравнить два момента времени точноИспользуйте операторы =, <, > напрямую
Нужно сравнить по календарному днюПриведите обе даты через НачалоДня() и сравнивайте на равенство
Нужна проверка попадания в периодИспользуйте пару условий >= НачалоПериода и <= КонецДня(КонецПериода) или МЕЖДУ в запросе
Дата может быть не заполненаСначала проверьте ЗначениеЗаполнено(), затем сравнивайте
Сравнение в отчёте СКДИспользуйте параметры периода и функцию КОНЕЦПЕРИОДА() в отборе

Разница между датами и сравнение по разности

Иногда сравнивать нужно не сами даты, а расстояние между ними: возраст сотрудника, длительность просрочки, стаж. Для этого служит функция запроса РАЗНОСТЬДАТ(Дата1, Дата2, Единица) — она возвращает целое число единиц (дней, месяцев, лет) между датами. Во встроенном языке прямого аналога нет: разность дат даёт число секунд, которое затем делят на 86400 для получения дней.

РазностьВСекундах = Дата2 - Дата1;

ДнейПросрочки = Цел(РазностьВСекундах / 86400);

Если ДнейПросрочки > 30 Тогда

// Критическая просрочка

КонецЕсли;

Учтите, что деление разности на 86400 считает «физические» сутки, а не календарные дни. Если нужны именно календарные дни между датами, приведите обе к началу дня перед вычитанием. Для месяцев и лет арифметика секунд не подходит — используйте РАЗНОСТЬДАТ в запросе или поэлементное сравнение через Год(), Месяц(), День().

Проверка корректности сравнения дат

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

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

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

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

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

После НачалоДня() обе даты равны, условие срабатывает

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

Даты выглядят одинаково, но равенство ложно — внутри разное время

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

В выборку попадают документы первого и последнего дня включительно

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

Документы последнего дня отсутствуют — граница задана без КонецДня()

Проверка пустой даты
Норма

Незаполненный реквизит определяется через ЗначениеЗаполнено() = Ложь

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

Пустая дата участвует в хронологическом сравнении и искажает логику

Частые вопросы

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

Приведите оба значения функцией НачалоДня() и сравнивайте результат: НачалоДня(Дата1) = НачалоДня(Дата2). Для сравнения «раньше/позже» по дню используйте те же приведённые значения с операторами < и >.

Как проверить, что дата не заполнена?

Два рабочих способа: сравнение с литералом '00010101' или функция ЗначениеЗаполнено(Дата) — она вернёт Ложь для пустой даты. В запросе используйте сравнение с ДАТАВРЕМЯ(1,1,1).

Почему условие Дата = ТекущаяДатаСеанса() никогда не срабатывает?

ТекущаяДатаСеанса() возвращает момент с точностью до секунды и постоянно меняется. Совпадение с заранее заданной датой до секунды практически невозможно. Сравнивайте по дню через НачалоДня() или по диапазону.

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

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

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

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

Как сравнить даты, хранящиеся в строковом реквизите?

Строковое сравнение дат хронологически некорректно. Преобразуйте строку в дату через Дата() с форматом "ГГГГММДДччммсс" или собственным разбором, и только потом сравнивайте. Хранить даты в строковых реквизитах не рекомендуется.

Итог

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

Даты в 1С сравниваются стандартными операторами, но тип всегда содержит время: для сравнения по дню приводите значения через НачалоДня() и КонецДня(). Пустую дату проверяйте через ЗначениеЗаполнено() или '00010101'. В запросах и СКД передавайте границы периодов с учётом конца дня, иначе данные последнего дня потеряются.