Разработка и Конфигурация · 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. Пара этих выражений — стандартный способ нормализовать границы периода прямо в тексте запроса, не готовя даты в коде.
Учтите: КОНЕЦПЕРИОДА работает только в тексте запроса. Если дата готовится в коде и передаётся параметром, приводить её к концу дня нужно до запроса — функцией КонецДня(). Смешивать оба подхода в одном месте не нужно, иначе получите двойное преобразование и запутаетесь при отладке.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док
|ГДЕ
| Док.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Начало, ДЕНЬ) И КОНЕЦПЕРИОДА(&Конец, ДЕНЬ)";
Запрос.УстановитьПараметр("Начало", ДатаНачала);
Запрос.УстановитьПараметр("Конец", ДатаОкончания);Какой способ выбрать: код, запрос или граница
Выбор зависит от того, где именно сравниваются даты и что является источником данных. Один и тот же результат достигается тремя путями, и у каждого есть свои ограничения.
Сравнение вариантов
Подходит, когда дата готовится до запроса и передаётся параметром. Просто и наглядно, но теряет доли секунды — документы с одинаковой секундой не различает.
Удобно, когда параметр приходит «как есть» и нормализация делается в тексте запроса. Не работает вне запроса.
Самый надёжный вариант для отборов по регистрам: параметр Период виртуальной таблицы или объект Граница с видом Включая учитывает момент времени целиком, включая доли секунды.
Тонкость в точности. Дата в 1С хранится с точностью до секунды, но момент времени документа включает также ссылку — два документа в одной секунде упорядочены по ссылке. Сравнение Документ.Дата <= КонецДня(Период) корректно по дате, однако для регистров, где важен именно момент времени, правильнее использовать виртуальные таблицы (РегистрНакопления.Товары.Остатки(&Период, ...)) или объект Граница:
ГраницаОкончания = Новый Граница(КонецДня(ДатаОкончания), ВидГраницы.Включая);
Типичные сценарии применения
Отбор документов за период в запросе
Пользователь выбирает период «с 01.03 по 15.03». Дата окончания приходит как 15.03.2026 00:00:00. Если сравнивать напрямую (Дата <= &КонецПериода), все документы за 15 марта, кроме проведённых ровно в полночь, выпадут из выборки. Решение — КОНЕЦПЕРИОДА в условии или КонецДня() при установке параметра.
Динамический список и произвольные отборы
В динамических списках с ручным текстом запроса границы периода нормализуют тем же КОНЕЦПЕРИОДА. Если отбор строится через СКД, стандартный период компоновки сам корректно обрабатывает дату окончания — вмешательство нужно только при нестандартных параметрах.
Сравнение дат в коде без запроса
При проверке «входит ли дата документа в период» в коде приводите обе даты к единой базе: начало — через НачалоДня(), конец — через КонецДня(). Сравнение «сырых» дат с разным временем — источник трудноуловимых ошибок, когда проверка то срабатывает, то нет.
- 1Проверьте, что обе даты периода заполнены (ЗначениеЗаполнено).
- 2Приведите начало периода: НачалоДня(ДатаНачала).
- 3Приведите конец периода: КонецДня(ДатаОкончания) — и присвойте результат.
- 4Передайте нормализованные даты параметрами в запрос или используйте КОНЕЦПЕРИОДА прямо в тексте.
- 5Выполните запрос и проверьте, что документы последнего дня попали в выборку.
Как проверить результат
Самый быстрый способ убедиться, что преобразование сработало, — вывести дату в сообщение или посмотреть её в отладчике. Формат вывода должен включать время, иначе разницы не видно.
Сообщить(Формат(КонецДня(ДатаПроверки), "ДЛФ=DT"));
// Выведет: 15.03.2026 23:59:59
Признак правильной работы отбора — в выборку попадают документы, проведённые в любое время последнего дня периода, включая вечерние. Если «вечерние» документы пропадают — дата окончания не приведена к концу дня.
Как проверить результат
Время равно 23:59:59, число не изменилось
Время 00:00:00 — результат не присвоен или применена НачалоДня
Документы за весь день присутствуют
Попадают только документы в 00:00:00 — условие без КОНЕЦПЕРИОДА
До преобразования выполнена проверка ЗначениеЗаполнено
В отбор уходит 01.01.0001 23:59:59
Типичные ошибки и ограничения
Отдельно о попытках «схитрить»: прибавлять к дате 86399 секунд (Дата + 86399) вместо КонецДня(). Технически это тот же результат, но код становится неочевидным, а при переходе через границу месяца или года ручная арифметика легче ломается. Штатная функция читается однозначно — используйте её.
Смежные функции работы с датами
КонецДня — часть семейства функций нормализации дат. Для начала периода есть НачалоДня(), НачалоНедели(), НачалоМесяца(), НачалоКвартала(), НачалоГода() и зеркальные им КонецНедели(), КонецМесяца(), КонецКвартала(), КонецГода(). Все они работают одинаково: принимают дату, возвращают новую с границей указанного периода.
В запросах этому семейству соответствуют НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА с параметрами НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. Знание всей пары «код/запрос» избавляет от лишних преобразований и делает отчёты предсказуемыми.
Что важно запомнить
КонецДня(Дата) в коде и КОНЕЦПЕРИОДА(&Дата, ДЕНЬ) в запросе возвращают 23:59:59 указанного дня. Результат функции нужно присваивать. Для отборов по регистрам надёжнее виртуальные таблицы и объект Граница. Перед применением проверяйте заполненность даты.
Частые вопросы
Чем КонецДня отличается от НачалоДня следующего дня?
КонецДня возвращает 23:59:59 текущего дня, а НачалоДня(Дата + 86400) — 00:00:00 следующего. Между ними нет «щели» по секундам, но сравнения строятся по-разному: для конца дня используют «меньше или равно», для начала следующего дня — строгое «меньше». Оба подхода корректны, важно не смешивать их в одном условии.
Работает ли КонецДня на клиенте в тонком и веб-клиенте?
Да, функция входит в число системных и доступна на любом клиенте без вызова сервера. Это делает её удобной для нормализации дат прямо в формах перед передачей в серверные процедуры.
Почему документ за последний день не попадает в отчёт, хотя КонецДня использован?
Проверьте, присвоен ли результат функции переменной и не применяется ли в запросе дополнительное условие по моменту времени или границе. Также убедитесь, что в параметр попадает именно преобразованная дата, а не исходная — типичная ситуация, когда параметр устанавливается до вызова КонецДня.
Как привести дату к концу дня в СКД?
В схеме компоновки используйте выражение КОНЕЦПЕРИОДА(&ПараметрДата, ДЕНЬ) в тексте запроса набора данных. Если применяется стандартный параметр «Период» типа СтандартныйПериод, его дата окончания уже содержит конец дня, и дополнительная обработка не требуется.
Что вернёт КонецДня для пустой даты?
Для значения 01.01.0001 00:00:00 функция вернёт 01.01.0001 23:59:59. Такая дата в отборе обычно бессмысленна, поэтому перед преобразованием стоит проверять заполненность через ЗначениеЗаполнено().
Можно ли использовать КонецДня в языке запросов?
Нет, в языке запросов этой функции нет. Её аналог — выражение КОНЕЦПЕРИОДА с параметром ДЕНЬ. Если дата готовится в коде, примените КонецДня() до установки параметра запроса.