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

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

Как получить конец дня в 1С

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

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

Типичная ситуация: разработчик фильтрует документы условием Дата <= &КонецПериода, передаёт туда дату без времени (то есть 00:00:00) и теряет все документы, проведённые в течение последнего дня. Причина именно в том, что «голая» дата в 1С — это начало суток, а не их конец. Ниже разобраны все способы корректно получить конец дня, использовать его в запросах и проверить результат.

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

Основной инструмент — встроенная функция КонецДня(Дата). Она принимает значение типа Дата и возвращает дату с временем 23:59:59 того же дня. Симметричная функция НачалоДня(Дата) возвращает 00:00:00. Обе доступны на клиенте и на сервере, не требуют контекста и работают в любой конфигурации.

ДатаДокумента = ТекущаяДатаСеанса();

КонецТекущегоДня = КонецДня(ДатаДокумента); // например, 15.03.2026 23:59:59

НачалоТекущегоДня = НачалоДня(ДатаДокумента); // 15.03.2026 0:00:00

Обратите внимание на источник даты: для получения «сегодня» в серверном коде корректно использовать ТекущаяДатаСеанса(), а не устаревшую ТекущаяДата(), которая на сервере возвращает дату сервера без учёта часового пояса сеанса и помечена как устаревшая. Из-за разницы часовых поясов «конец дня» по времени сервера и по времени пользователя могут оказаться разными календарными датами.

Если нужна дата произвольного дня, её можно сконструировать функцией Дата(Год, Месяц, День) и передать в КонецДня():

КонецЯнваря31 = КонецДня(Дата(2026, 1, 31)); // 31.01.2026 23:59:59

Конец дня в языке запросов

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

ВЫБРАТЬ

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

Реализация.Дата

ИЗ

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

ГДЕ

Реализация.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)

Такой запрос выберет все документы за один календарный день независимо от времени их проведения. Функция НАЧАЛОПЕРИОДА() работает зеркально и возвращает 00:00:00. Использование этих функций предпочтительнее ручной арифметики: запрос остаётся читаемым, а оптимизатор СУБД корректно обрабатывает такие условия.

bsl
КонецДня = КонецДня(ТекущаяДатаСеанса()); // 23:59:59 сегодня
// В запросе: ГДЕ Док.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)

Конец дня в параметрах виртуальных таблиц

При обращении к виртуальным таблицам регистров (Остатки, Обороты, ОстаткиИОбороты) границы периода передаются через параметры. Здесь есть нюанс: если передать в параметр «Конец периода» значение КонецДня(Дата), движения, совершённые ровно в 23:59:59, будут учтены, но регистраторы с типичным временем документа попадают в выборку корректно. Однако более надёжный способ — использовать тип Граница с явным указанием включения.

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

Запрос.УстановитьПараметр("КонецПериода", ГраницаКонца);

Конструкция Новый Граница(Значение, ВидГраницы.Включая) гарантирует, что все движения до конца дня включительно попадут в результат, даже если по какой-то причине время движения окажется на границе. Это особенно важно для остатков: остаток «на конец дня» должен включать все документы этого дня.

Получение конца дня от произвольной даты и сдвиг дат

Часто нужен конец не сегодняшнего, а произвольного дня: вчерашнего, завтрашнего или даты из реквизита документа. Для сдвига дат в 1С применяется функция ДобавитьКДате(Дата, ТипСдвига, Количество). Она корректно обрабатывает переходы через месяцы и годы, в отличие от прибавления секунд числом.

КонецВчера = КонецДня(ДобавитьКДате(ТекущаяДатаСеанса(), "ДЕНЬ", -1));

КонецНедели = КонецНедели(ТекущаяДатаСеанса()); // воскресенье 23:59:59

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

Конец дня для даты из строки или реквизита

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

Типичные ошибки при работе с границей дня

Самая распространённая ошибка — передача в запрос даты без времени в качестве верхней границы. Условие Дата <= &КонецПериода, где параметр равен 15.03.2026 0:00:00, отсекает весь день 15 марта. Пользователь видит в отчёте «потерянные» документы, хотя физически они в базе есть.

Вторая ошибка — использование конструкции вида КонецДня(Дата) + 1 с последующим сравнением «строго меньше». Это рабочий приём (получается 00:00:00 следующего дня), но он менее читаем, чем КонецДня() с «меньше или равно», и при смешивании обоих подходов в одном коде легко получить двойной учёт граничной секунды.

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

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

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

Проверить значение, которое вернула функция, проще всего выводом в сообщение или в консоль кода с форматированием:

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

Формат ДЛФ=DT выводит дату с временем, и вы сразу видите, что время равно 23:59:59. Если выводится 00:00:00 — значит, вместо КонецДня() где-то использована исходная дата или НачалоДня().

Для проверки запроса возьмите тестовый документ, проведённый в середине дня (например, в 14:30), и убедитесь, что он попадает в выборку за этот день. Затем проверьте граничный случай: документ с ручной установкой времени 23:59:59. Оба должны присутствовать в результате.

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

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

Значение функции КонецДня()
Норма

Время равно 23:59:59 нужной даты

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

Время 00:00:00 — применена не та функция или дата без времени

Запрос за один день
Норма

Документы за весь день, включая вечерние, в выборке

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

Пропадают документы после 00:00 последнего дня

Остатки на конец дня
Норма

Учтены все движения дня, включая последний документ

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

Остаток не сходится с отчётом за день на сумму поздних документов

Выбор подхода под задачу

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

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

Как выбрать действие

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

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

Конец дня — это 23:59:59, и в 1С его даёт функция КонецДня() в коде и КОНЕЦПЕРИОДА(Дата, ДЕНЬ) в запросах. Для виртуальных таблиц регистров используйте Границу с видом «Включая». Главная ошибка — передача даты без времени как верхней границы периода.

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

Чем КонецДня() отличается от КОНЕЦПЕРИОДА()?

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

Почему в отчёт не попадают документы последнего дня?

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

Можно ли получить конец дня прибавлением секунд к началу дня?

Технически да: НачалоДня(Дата) + 86399. Но это менее читаемо и чревато ошибками при сдвиге на другой день. Встроенная КонецДня() предпочтительнее.

Как получить конец вчерашнего дня?

КонецДня(ДобавитьКДате(ТекущаяДатаСеанса(), "ДЕНЬ", -1)). Функция ДобавитьКДате корректно обработает переход через границу месяца и года.

Учитывает ли КонецДня() часовой пояс пользователя?

Функция сама по себе работает с переданной датой и пояс не знает. Часовой пояс определяется тем, как получена исходная дата: ТекущаяДатаСеанса() учитывает пояс сеанса, а серверная дата — нет.

Что вернёт КонецДня(), если передать дату со временем?

Время будет отброшено, и функция вернёт 23:59:59 того же календарного дня, к которому относится переданная дата.