Разработка и Конфигурация · 12 мин
Как сравнить даты в 1С: практическое руководство
Как сравнить даты в 1С: операторы сравнения, РазностьДат, Граница, сравнение в запросах, работа с пустой датой и типичные ошибки разработчиков.
Сравнение дат — одна из самых частых операций при разработке на платформе 1С:Предприятие. Она нужна при проверке периодов действия договоров, отборе документов за интервал, расчёте просрочек, контроле последовательности проведения и во многих других задачах. При этом у новичков сравнение дат регулярно вызывает ошибки: сравнивают строковые представления, забывают про время в составе даты или некорректно обрабатывают пустые значения.
Встроенный язык 1С поддерживает прямое сравнение значений типа «Дата» операторами =, <>, >, <, >=, <=, а также предоставляет функции для вычисления разности дат и получения границ периодов. В запросах используется свой синтаксис, включая виртуальные таблицы с параметрами периодов.
Материал охватывает сравнение дат во встроенном языке, в запросах, типовые сценарии вроде проверки попадания в интервал, а также разбор ошибок, которые приводят к неверным результатам даже при синтаксически правильном коде.
Базовое сравнение дат операторами
Тип «Дата» в 1С — это момент времени с точностью до секунды. Значения этого типа упорядочены, поэтому все стандартные операторы сравнения работают без преобразований:
Дата1 = '20260115';
Дата2 = '20260320';
Если Дата1 < Дата2 Тогда
Сообщить("Дата1 раньше Дата2");
КонецЕсли;
Если Дата1 = Дата2 Тогда
Сообщить("Даты совпадают");
КонецЕсли;
Дата-литерал записывается в одинарных кавычках в формате ГГГГММДД, при необходимости с временем: '20260115143000' — 15 января 2026 года, 14:30:00. Если время не указано, оно равно 00:00:00 — это важно помнить при сравнениях на равенство.
Операторы сравнения возвращают значение типа «Булево», поэтому их можно использовать не только в Если, но и в выражениях: Просрочен = (ТекущаяДата() > СрокОплаты);. Такой приём делает код короче и читаемее, чем ветвление с присвоением Истина/Ложь.
Если Документ.Дата >= НачалоДня(ТекущаяДата()) Тогда
// документ от сегодняшнего дня
КонецЕсли;Учёт времени при сравнении: типичная ловушка
Самая частая причина «неправильного» сравнения — скрытое время в составе даты. Документ, проведённый 15 марта в 14:23:47, не равен дате '20260315', потому что литерал означает 15 марта 00:00:00. Сравнение на равенство вернёт Ложь, хотя «дата та же».
Чтобы сравнивать даты без учёта времени, приводите обе стороны к началу дня функцией НачалоДня():
Если НачалоДня(Документ.Дата) = НачалоДня(ТекущаяДата()) Тогда
// документ проведён сегодня
КонецЕсли;
Аналогично работают функции НачалоМесяца(), НачалоКвартала(), НачалоГода(), НачалоНедели() и их «конечные» пары. Например, проверка, что документ относится к текущему месяцу: НачалоМесяца(Документ.Дата) = НачалоМесяца(ТекущаяДата()).
Проверка попадания даты в интервал
Проверка «дата внутри периода» — стандартная задача. Делайте её двойным условием с явными границами:
Если ПроверяемаяДата >= НачалоПериода
И ПроверяемаяДата <= КонецДня(КонецПериода) Тогда
// дата внутри периода
КонецЕсли;
Обратите внимание на КонецДня(КонецПериода): если пользователь указывает конец периода как «31 марта», то значение даты — 31.03 00:00:00, и документ от 31 марта 10:00 формально выпадет из интервала. Либо расширяйте правую границу через КонецДня(), либо используйте строгое неравенство с началом следующего дня: ПроверяемаяДата < КонецПериода + 86400.
Второй подход с «строго меньше начала следующего дня» надёжнее, потому что не зависит от того, как именно заполнена граница. Прибавление числа к дате в 1С означает прибавление секунд, поэтому сутки — это 86400.
- 1Определите, включительны ли границы периода по смыслу задачи
- 2Приведите левую границу к НачалоДня() или убедитесь, что время нулевое
- 3Правую границу расширьте через КонецДня() или замените на начало следующего дня со строгим <
- 4Протестируйте условие на граничных значениях: документ ровно в 00:00:00 первого дня и в 23:59:59 последнего
Вычисление разности дат
Когда нужно не просто сравнить, а узнать, насколько даты различаются, используется функция РазностьДат(Дата1, Дата2, ЕдиницаИзмерения). Она возвращает количество целых единиц (секунд, минут, часов, дней, месяцев и т.д.) между двумя датами:
ДнейПросрочки = РазностьДат(СрокОплаты, ТекущаяДата(), "ДЕНЬ");
Если ДнейПросрочки > 0 Тогда
// оплата просрочена
КонецЕсли;
Тонкость: РазностьДат считает количество пересечённых границ единицы измерения, а не полных интервалов. Разность между 23:00 и 01:00 следующего дня в единице «ДЕНЬ» равна 1, хотя прошло два часа. Если нужна именно длительность, вычитайте даты напрямую: Секунд = Дата2 - Дата1; — результат в секундах, который дальше делится на 3600 или 86400.
Для сдвига даты на заданный интервал есть функция ДобавитьКДате(Дата, Единица, Количество). Она корректно обрабатывает месяцы разной длины, чего не сделать простым прибавлением секунд.
Сравнение дат в запросах
В языке запросов 1С даты сравниваются теми же операторами, но значения обычно передаются параметрами:
ВЫБРАТЬ
Реализация.Ссылка
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
Оператор МЕЖДУ включает обе границы, поэтому параметр &КонецПериода нужно заполнять значением КонецДня(Период), иначе документы последнего дня с ненулевым временем потеряются. Это самая частая причина «отчёт не видит документы за последний день».
Для сравнения только по дате без времени в запросе используются функции НАЧАЛОПЕРИОДА(Поле, ДЕНЬ) и КОНЕЦПЕРИОДА(Поле, ДЕНЬ). Условие вида НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ) = &День корректно, но не использует индекс по полю Дата — на больших таблицах предпочтительнее сравнение по диапазону.
Виртуальные таблицы регистров (Остатки, Обороты, СрезПоследних) принимают параметры периода отдельно. Для СрезаПоследних важно: граница включается, поэтому при необходимости «состояние на начало дня» передают объект Граница с видом «Исключая» или предыдущий момент времени.
Пустая дата и проверка заполненности
Пустая дата в 1С — это '00010101' (1 января года 1, 00:00:00). Сравнение с ней работает как обычно, но проверять заполненность правильнее функцией ЗначениеЗаполнено():
Если НЕ ЗначениеЗаполнено(Договор.ДатаОкончания) Тогда
// договор бессрочный
КонецЕсли;
В запросах пустую дату проверяют сравнением с литералом ДАТАВРЕМЯ(1,1,1): ГДЕ Документ.ДатаОплаты = ДАТАВРЕМЯ(1,1,1). Функция ДАТАВРЕМЯ(год, месяц, день[, часы, минуты, секунды]) — стандартный способ задать дату прямо в тексте запроса без параметра.
Помните, что пустая дата меньше любой реальной даты. Условие ДатаОкончания >= ТекущаяДата() для бессрочного договора с незаполненной датой вернёт Ложь — и договор ошибочно попадёт в «истёкшие». Обрабатывайте пустые значения отдельной веткой условия.
Как выбрать способ сравнения
Сравнение дат в разных часовых поясах и сеансовые даты
Функция ТекущаяДата() возвращает дату сеанса, которая может отличаться от времени сервера и от времени клиентского компьютера — в зависимости от настроек информационной базы. В клиент-серверном режиме код, выполняемый на сервере, получит серверное время, а на клиенте — клиентское.
Если сравниваете дату документа с «сейчас» в коде, который может выполняться и на клиенте, и на сервере, возможны расхождения на границе суток. Для ответственных проверок (закрытие периода, контроль сроков) выполняйте сравнение на сервере с единым источником времени.
Для универсального времени есть функция ТекущаяУниверсальнаяДата() (UTC). Она полезна при обмене данными между базами в разных часовых поясах, но для бухгалтерской логики обычно нужна именно локальная дата сеанса.
Проверка результата и контрольные точки
После реализации сравнения проверьте его на граничных случаях: даты с нулевым и ненулевым временем, первый и последний день периода, пустая дата, одинаковые даты. Большинство дефектов в логике сравнения дат проявляются именно на границах, а не на «средних» значениях.
Как проверить корректность сравнения
Документ входит в выборку
Документ теряется — правая граница без КонецДня()
Равенство срабатывает после НачалоДня() обеих сторон
Равенство ложное из-за времени — нужно приведение
Обрабатывается отдельной веткой ЗначениеЗаполнено()
Попадает в просроченные из-за сравнения пустой даты
Условие по диапазону с параметрами, индекс используется
НАЧАЛОПЕРИОДА на поле в условии — полное сканирование
Быстрый способ отладки — вывести сравниваемые значения через Сообщить() или посмотреть в отладчике в формате с секундами. Если значения визуально совпадают, а сравнение не работает — проверьте типы: иногда в переменной оказывается строка, полученная из Формат() или из внешнего источника.
Что важно запомнить
Даты в 1С сравниваются напрямую операторами; тип «Дата» включает время, поэтому для календарных сравнений используйте НачалоДня()/КонецДня(). В запросах передавайте границы параметрами с КонецДня(), пустую дату проверяйте через ЗначениеЗаполнено() или ДАТАВРЕМЯ(1,1,1). Большинство ошибок связано со скрытым временем и пустыми значениями — проверяйте граничные случаи.
Частые вопросы
Можно ли сравнивать дату со строкой вида "15.03.2026"?
Нет, прямое сравнение даты и строки некорректно. Строку нужно преобразовать в дату функцией Дата() (в толстом клиенте) или разобрать вручную и собрать через Дата(год, месяц, день). Сравнение строк лексикографическое: "09.01.2026" окажется «больше», чем "10.01.2026", что ломает логику.
Как сравнить только время без даты?
Штатной функции «время из даты» нет. Обычно вычитают начало дня: СекундыСПолуночи = ДатаСоВременем - НачалоДня(ДатаСоВременем), и сравнивают полученное число секунд. Либо извлекают часы и минуты функциями Час() и Минута().
Почему РазностьДат возвращает 1, хотя прошло два часа?
РазностьДат считает количество пересечённых границ единицы измерения. Между 23:00 и 01:00 есть одна граница суток, поэтому результат в единице «ДЕНЬ» равен 1. Для фактической длительности вычитайте даты напрямую — получите секунды.
Как в запросе задать дату без параметра?
Функцией ДАТАВРЕМЯ(год, месяц, день, часы, минуты, секунды), например ДАТАВРЕМЯ(2026, 3, 31, 23, 59, 59). Пустая дата записывается как ДАТАВРЕМЯ(1,1,1).
Чем отличается Граница от обычной даты при сравнении?
Граница — это объект, включающий момент времени и признак включения (Включая/Исключая). Она нужна для параметров виртуальных таблиц регистров, где важно, попадает ли запись ровно на границе в результат. Обычная дата всегда трактуется как включённая граница.
ТекущаяДата() на клиенте и сервере даёт разные значения — это нормально?
Да, если настроены разные часовые пояса сеанса или смещение времени клиента. Для контрольных проверок (закрытие периода, сроки) выполняйте сравнение на сервере, чтобы источник времени был единым, либо используйте ТекущаяДатаСеанса() осознанно с учётом настроек ИБ.