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

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

Как привести дату к концу дня в 1С

Как привести дату к концу дня в 1С: функция КонецДня(), выражение КОНЕЦПЕРИОДА в запросах, типичные ошибки сравнения дат и границы периодов.

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

Штатное решение — встроенная функция КонецДня() во встроенном языке и выражение КОНЕЦПЕРИОДА в языке запросов. Обе конструкции возвращают дату с временем 23:59:59, то есть последнюю секунду указанного дня. Ниже разобраны оба способа, тонкости их применения, альтернатива через виртуальные таблицы и типичные ошибки.

Функция КонецДня() во встроенном языке

Функция КонецДня() доступна везде, где выполняется код на встроенном языке: в модулях объектов, форм, общих модулях, внешних обработках. Она принимает один параметр — значение типа «Дата» — и возвращает новую дату с тем же числом, но временем 23:59:59.

ДатаОкончания = КонецДня(ДатаПользователя);

// Если ДатаПользователя = 15.03.2026 10:20:00,

// то ДатаОкончания = 15.03.2026 23:59:59

Исходное значение функция не меняет — она возвращает новое. Частая ошибка новичков: вызвать КонецДня(МояДата) и не присвоить результат. После такого вызова переменная МояДата останется прежней.

Если исходное значение содержит пустую дату (01.01.0001), функция вернёт 01.01.0001 23:59:59. Перед использованием стоит проверять заполненность через ЗначениеЗаполнено(), чтобы не строить отборы по фиктивному периоду.

Выражение КОНЕЦПЕРИОДА в запросах

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

ГДЕ

Документ.Дата МЕЖДУ &НачалоПериода И КОНЕЦПЕРИОДА(&КонецПериода, ДЕНЬ)

Есть и зеркальное выражение НАЧАЛОПЕРИОДА(Дата, ДЕНЬ), которое возвращает 00:00:00. Пара этих выражений — стандартный способ нормализовать границы периода прямо в тексте запроса, не готовя даты в коде.

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

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

Какой способ выбрать: код, запрос или граница

Выбор зависит от того, где именно сравниваются даты и что является источником данных. Один и тот же результат достигается тремя путями, и у каждого есть свои ограничения.

Сравнение вариантов

КонецДня() в коде

Подходит, когда дата готовится до запроса и передаётся параметром. Просто и наглядно, но теряет доли секунды — документы с одинаковой секундой не различает.

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

Удобно, когда параметр приходит «как есть» и нормализация делается в тексте запроса. Не работает вне запроса.

Граница и виртуальные таблицы

Самый надёжный вариант для отборов по регистрам: параметр Период виртуальной таблицы или объект Граница с видом Включая учитывает момент времени целиком, включая доли секунды.

Тонкость в точности. Дата в 1С хранится с точностью до секунды, но момент времени документа включает также ссылку — два документа в одной секунде упорядочены по ссылке. Сравнение Документ.Дата <= КонецДня(Период) корректно по дате, однако для регистров, где важен именно момент времени, правильнее использовать виртуальные таблицы (РегистрНакопления.Товары.Остатки(&Период, ...)) или объект Граница:

ГраницаОкончания = Новый Граница(КонецДня(ДатаОкончания), ВидГраницы.Включая);

Типичные сценарии применения

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

Пользователь выбирает период «с 01.03 по 15.03». Дата окончания приходит как 15.03.2026 00:00:00. Если сравнивать напрямую (Дата <= &КонецПериода), все документы за 15 марта, кроме проведённых ровно в полночь, выпадут из выборки. Решение — КОНЕЦПЕРИОДА в условии или КонецДня() при установке параметра.

Динамический список и произвольные отборы

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

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

При проверке «входит ли дата документа в период» в коде приводите обе даты к единой базе: начало — через НачалоДня(), конец — через КонецДня(). Сравнение «сырых» дат с разным временем — источник трудноуловимых ошибок, когда проверка то срабатывает, то нет.

Порядок действий для отбора за период
  1. 1
    Проверьте, что обе даты периода заполнены (ЗначениеЗаполнено).
  2. 2
    Приведите начало периода: НачалоДня(ДатаНачала).
  3. 3
    Приведите конец периода: КонецДня(ДатаОкончания) — и присвойте результат.
  4. 4
    Передайте нормализованные даты параметрами в запрос или используйте КОНЕЦПЕРИОДА прямо в тексте.
  5. 5
    Выполните запрос и проверьте, что документы последнего дня попали в выборку.

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

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

Сообщить(Формат(КонецДня(ДатаПроверки), "ДЛФ=DT"));

// Выведет: 15.03.2026 23:59:59

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

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

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

Значение после КонецДня()
Норма

Время равно 23:59:59, число не изменилось

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

Время 00:00:00 — результат не присвоен или применена НачалоДня

Выборка за последний день периода
Норма

Документы за весь день присутствуют

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

Попадают только документы в 00:00:00 — условие без КОНЕЦПЕРИОДА

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

До преобразования выполнена проверка ЗначениеЗаполнено

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

В отбор уходит 01.01.0001 23:59:59

Типичные ошибки и ограничения

Типичные ошибки
01
Вызов КонецДня(Дата) без присваивания — переменная не меняется, отбор работает неправильно.
02
Сравнение Дата <= &КонецПериода без приведения — выпадают все документы последнего дня, кроме полуночных.
03
Применение КонецДня к дате окончания, которая уже является границей момента времени, вместо использования объекта Граница или виртуальной таблицы.
04
Двойное преобразование: КонецДня() в коде и КОНЕЦПЕРИОДА в запросе одновременно — работает, но запутывает сопровождение.
05
Игнорирование пустой даты — отбор строится по 01.01.0001 и возвращает пустой или неожиданный результат.

Отдельно о попытках «схитрить»: прибавлять к дате 86399 секунд (Дата + 86399) вместо КонецДня(). Технически это тот же результат, но код становится неочевидным, а при переходе через границу месяца или года ручная арифметика легче ломается. Штатная функция читается однозначно — используйте её.

Смежные функции работы с датами

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

В запросах этому семейству соответствуют НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА с параметрами НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. Знание всей пары «код/запрос» избавляет от лишних преобразований и делает отчёты предсказуемыми.

Итог

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

КонецДня(Дата) в коде и КОНЕЦПЕРИОДА(&Дата, ДЕНЬ) в запросе возвращают 23:59:59 указанного дня. Результат функции нужно присваивать. Для отборов по регистрам надёжнее виртуальные таблицы и объект Граница. Перед применением проверяйте заполненность даты.

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

Чем КонецДня отличается от НачалоДня следующего дня?

КонецДня возвращает 23:59:59 текущего дня, а НачалоДня(Дата + 86400) — 00:00:00 следующего. Между ними нет «щели» по секундам, но сравнения строятся по-разному: для конца дня используют «меньше или равно», для начала следующего дня — строгое «меньше». Оба подхода корректны, важно не смешивать их в одном условии.

Работает ли КонецДня на клиенте в тонком и веб-клиенте?

Да, функция входит в число системных и доступна на любом клиенте без вызова сервера. Это делает её удобной для нормализации дат прямо в формах перед передачей в серверные процедуры.

Почему документ за последний день не попадает в отчёт, хотя КонецДня использован?

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

Как привести дату к концу дня в СКД?

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

Что вернёт КонецДня для пустой даты?

Для значения 01.01.0001 00:00:00 функция вернёт 01.01.0001 23:59:59. Такая дата в отборе обычно бессмысленна, поэтому перед преобразованием стоит проверять заполненность через ЗначениеЗаполнено().

Можно ли использовать КонецДня в языке запросов?

Нет, в языке запросов этой функции нет. Её аналог — выражение КОНЕЦПЕРИОДА с параметром ДЕНЬ. Если дата готовится в коде, примените КонецДня() до установки параметра запроса.