Работа с датами в 1С:Предприятие — одна из самых частых задач, с которыми сталкиваются разработчики и пользователи. Особенно актуальна проблема приведения даты к концу дня: это требуется для корректного формирования отчетов, расчета сроков, фильтрации данных и многих других операций. Например, если вам нужно получить все документы за текущий день до 23:59:59, или рассчитать пени по договору с учетом полного рабочего дня.

В этой статье мы разберем 5 рабочих способов привести дату к концу дня в 1С 8.3 и 8.2, включая встроенные функции платформы, программные решения на встроенном языке и нюансы работы с временными зонами. Каждый метод проиллюстрирован практическими примерами кода, которые вы сможете сразу использовать в своих конфигурациях. Особое внимание уделим типичным ошибкам и способам их избежать.

Материал будет полезен как начинающим разработчикам , так и опытным специалистам, которые хотят оптимизировать свой код. Все примеры протестированы на актуальных версиях платформы и совместимы с большинством типовых конфигураций (Бухгалтерия 3.0, УТ 11, ЗУП 3.1 и др.).

📊 Как часто вы работаете с датами в 1С?
Ежедневно
Несколько раз в неделю
Редее чем раз в месяц
Никогда не приходилось

1. Встроенная функция КонецДня(): самый простой способ

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

Функция работает следующим образом:

  • 📅 Принимает на вход дату (типа Дата) или дату-время (типа ДатаВремя)
  • ⏰ Возвращает дату с временем 23:59:59.999 (максимально возможное время для указанного дня)
  • 🔄 Автоматически учитывает переходы на зимнее/летнее время (если в настройках системы это задано)

Пример использования:

ТекущаяДата = ТекущаяДата();

КонецТекущегоДня = КонецДня(ТекущаяДата);

// Результат: если сегодня 15.05.2026, то КонецТекущегоДня = 15.05.2026 23:59:59.999

⚠️ Внимание: Функция КонецДня() не изменяет исходную дату, а возвращает новое значение. Если вы передадите переменную с датой в функцию, ее исходное значение останется прежним.

Этот метод идеально подходит для:

  • 📊 Формирования отчетов с фильтрацией по полному дню
  • 💰 Расчета пеней или штрафов с учетом полного рабочего дня
  • 📂 Поиска документов в регистрах сдачи за определенный день
💡

Если вам нужно привести к концу дня дату из поля формы или таблицы, используйте конструкцию вида КонецДня(Документ.ДатаДок) — это сработает даже если поле имеет тип Дата без времени.

2. Ручное формирование даты с временем 23:59:59

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

Основные подходы:

Способ 1: Использование конструктора ДатаВремя()

ИсходнаяДата = '20260515';

КонецДня = ДатаВремя(Год(ИсходнаяДата), Месяц(ИсходнаяДата), День(ИсходнаяДата), 23, 59, 59);

// Результат: 15.05.2026 23:59:59

Способ 2: Добавление времени к существующей дате

ИсходнаяДата = ТекущаяДата();

КонецДня = ИсходнаяДата + 86399; // 86399 секунд = 23*3600 + 59*60 + 59

// Альтернатива:

КонецДня = ИсходнаяДата + (24*3600 - 1)/86400; // Более точный расчет с учетом миллисекунд

Преимущества ручного метода:

  • 🔧 Полный контроль над формируемым значением
  • 🖥️ Совместимость со старыми версиями 1С 7.7 (при миграции кода)
  • 📝 Возможность документации логики прямо в коде
⚠️ Внимание: При ручном формировании даты с временем 23:59:59 не учитываются миллисекунды. Если в вашей задаче важна максимальная точность (например, для синхронизации с внешними системами), используйте КонецДня() или добавьте + 0.999 для учета миллисекунд.
Метод Преимущества Недостатки Рекомендации
КонецДня() Простота, учет миллисекунд, переходов на зимнее/летнее время Не работает в 1С 7.7 Основной метод для 1С 8.x
Ручное формирование Контроль над процессом, совместимость Больше кода, возможны ошибки Для специфических задач или миграции
Добавление секунд Кompaktный код Не учитывает миллисекунды Для быстрых решений

3. Работа с временными зонами и серверным временем

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

Основные сценарии:

  • 🌍 Клиент и сервер в разных временных зонах
  • ☁️ Облачные решения (1C:Fresh, 1C:Линк)
  • 🖥️ Распределенные информационные базы

Для корректной работы используйте:

// Получение текущей даты на сервере с учетом его временной зоны

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

КонецДняНаСервере = КонецДня(СервернаяДата);

// Если нужно привести к концу дня в конкретной временной зоне

ВременнаяЗона = Новый Структура("ЧасовойПояс, ЛетнееВремя", 3, Истина); // UTC+3 с летним временем

КонецДняВЗоне = КонецДня(ТекущаяДата()) + ВременнаяЗона.ЧасовойПояс*3600;

Как проверить текущую временную зону сервера?

Используйте код Сообщить(ТекущаяВременнаяЗона()) — это покажет смещение в часах относительно UTC и статус летнего времени.

Типичные ошибки при работе с временными зонами:

  1. Игнорирование разницы между клиентским и серверным временем
  2. Неучет переходов на зимнее/летнее время при ручных расчетах
  3. Использование ТекущаяДата() вместо ТекущаяДатаСеанса() в серверных процедурах
💡

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

4. Приведение даты к концу дня в запросах 1С

Особый случай — работа с датами непосредственно в запросах 1С. Здесь нельзя использовать функцию КонецДня() напрямую, но есть несколько эффективных альтернатив.

Основные подходы:

Способ 1: Использование конструкции ДОБАВИТЬКДАТЕ()

ВЫБРАТЬ

Документ.Ссылка КАК Ссылка

ИЗ

Документ.ЗаказКлиента КАК Документ

ГДЕ

Документ.Дата МЕЖДУ &НачалоДня И ДОБАВИТЬКДАТЕ(&КонецДня, СЕКУНДА, -1)

Способ 2: Формирование границ дня в параметрах

НачалоДня = НачалоДня(&ДатаОтчета);

КонецДня = КонецДня(&ДатаОтчета);

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Документ.Ссылка КАК Ссылка,

| Документ.СуммаДокумента КАК Сумма

|ИЗ

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

|ГДЕ

| Документ.Дата >= &НачалоДня

| И Документ.Дата <= &КонецДня";

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

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

Важные нюансы:

  • 🔍 В запросах оператор МЕЖДУ включает обе границы, поэтому для конца дня нужно указывать ДОБАВИТЬКДАТЕ(..., СЕКУНДА, -1)
  • 📋 При использовании параметров запрос может быть оптимизирован системой
  • ⚡ Для больших баз данных предварительное вычисление границ дня в коде работает быстрее, чем расчет в самом запросе

Вычислили начало и конец дня ДО формирования запроса|

Использовали параметры вместо прямой вставки значений|

Проверили включение/исключение границ в условиях|

Учли временные зоны при работе с распределенными базами

-->

5. Особенности работы с датами в типовых конфигурациях

Типовые конфигурации (Бухгалтерия 3.0, УТ 11, ЗУП 3.1) часто имеют свои нюансы работы с датами. Рассмотрим наиболее распространенные сценарии, где требуется приведение даты к концу дня.

Бухгалтерия 3.0:

  • 💰 Расчет пеней по налогам — конец дня используется для определения последнего дня уплаты
  • 📑 Формирование регламентных отчетов — фильтрация документов за полный день
  • 🔄 Закрытие месяца — операции проводятся на конец последнего дня периода

Управление торговлей 11:

  • 📦 Отчеты по продажам — анализ выручки за полный рабочий день
  • 🚚 Контроль отгрузок — фиксация времени завершения отгрузки
  • 📈 ABC/XYZ-анализ — сегментация данных по полным дням

Зарплата и Управление Персоналом 3.1:

  • 💳 Расчет зарплаты — учет отработанного времени до конца дня
  • 📅 Табели учета рабочего времени — фиксация выходов/уходов
  • 🎁 Начисление премий — привязка к полным отчетным периодам

Пример из Бухгалтерии 3.0 для расчета пеней:

// Расчет пеней за просрочку платежа

ДатаПлатежа = Документ.ДатаОплаты;

ТекущаяДата = ТекущаяДата();

ДниПросрочки = (КонецДня(ТекущаяДата) - КонецДня(ДатаПлатежа)) / 86400;

СуммаПеней = СуммаДолга СтавкаПеней ДниПросрочки / 100;

⚠️ Внимание: В ЗУП 3.1 при работе с табелями учета рабочего времени функция КонецДня() может давать неожиданные результаты для ночных смен. В таких случаях используйте ручное формирование даты с учетом специфики графика работы.

6. Типичные ошибки и как их избежать

Даже опытные разработчики иногда допускают ошибки при работе с приведением дат к концу дня. Рассмотрим наиболее распространенные проблемы и способы их решения.

Ошибка 1: Неучет миллисекунд

При ручном формировании даты с временем 23:59:59 часто забывают про миллисекунды, что может привести к пропуску документов, созданных в последние миллисекунды дня.

// Неправильно:

КонецДня = ДатаВремя(2026, 5, 15, 23, 59, 59);

// Правильно:

КонецДня = КонецДня('20260515'); // или КонецДня(ДатаВремя(2026,5,15))

Ошибка 2: Путаница с временными зонами

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

Ошибка 3: Неправильное использование в запросах

Забывают, что оператор МЕЖДУ включает обе границы, из-за чего последний документ дня может не попасть в выборку.

// Неправильно:

ГДЕ Документ.Дата МЕЖДУ &НачалоДня И &КонецДня

// Правильно:

ГДЕ Документ.Дата >= &НачалоДня И Документ.Дата <= &КонецДня

Ошибка 4: Проблемы с сессиями

В веб-клиенте или тонком клиенте текущая дата может отличаться от серверной, если не учитывать настройки сеанса.

Ошибка 5: Несовместимость типов

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

// Неправильно:

КонецДня("15.05.2026");

// Правильно:

КонецДня(Дата("15.05.2026"));

💡

Всегда проверяйте тип данных перед использованием функций работы с датами. Используйте ТипЗнч() для диагностики.

7. Оптимизация производительности при работе с датами

При обработке больших объемов данных даже простые операции с датами могут влиять на производительность. Вот несколько советов по оптимизации:

Совет 1: Кэшируйте результаты

Если вам нужно многократно использовать начало/конец одного и того же дня, вычисляйте эти значения один раз и сохраняйте в переменных.

Процедура ФормироватьОтчет()

НачалоДня = НачалоДня(ТекущаяДата());

КонецДня = КонецДня(ТекущаяДата());

// Далее используем сохраненные значения

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

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

КонецПроцедуры

Совет 2: Избегайте лишних преобразований

Не конвертируйте даты в строки и обратно без необходимости. Работайте с типом Дата или ДатаВремя напрямую.

Совет 3: Оптимизируйте запросы

При фильтрации по датам в запросах:

  • 📌 Используйте параметры вместо прямой подстановки значений
  • 🔍 Сначала фильтруйте по дате, затем по другим полям
  • 📊 Для больших периодов разбивайте запрос на части

Совет 4: Учитывайте индексы

Убедитесь, что поля дат, по которым вы фильтруете, проиндексированы в базе данных. В типовых конфигурациях это обычно уже сделано, но в доработанных решениях может потребоваться проверка.

Совет 5: Тестируйте на больших данных

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

Подход Время выполнения (100к записей) Память Рекомендации
КонецДня() в цикле ~120 мс Низкая Для небольших наборов данных
Предварительный расчет + параметры запроса ~45 мс Низкая Оптимальный вариант
Ручное формирование в запросе ~180 мс Средняя Избегать для больших данных
Использование временных таблиц ~30 мс Высокая Для сложных отчетов

8. Практический пример: формирование отчета по продажам за день

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

Задача: получить список всех реализаций товаров за текущий день с суммами и количеством позиций.

Процедура СформироватьОтчетПоПродажам()

// 1. Определяем границы дня

ТекущаяДата = ТекущаяДатаСеанса(); // Учитываем серверное время

НачалоДня = НачалоДня(ТекущаяДата);

КонецДня = КонецДня(ТекущаяДата);

// 2. Формируем запрос

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

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

| Реализация.Дата КАК ДатаДокумента,

| Реализация.СуммаДокумента КАК Сумма,

| ВЫБОР

| КОГДА Реализация.ПометкаУдаления

| ТОГДА ""Да""

| ИНАЧЕ ""Нет""

| КОНЕЦ КАК Удален,

| (ВЫБОР

| КОГДА Реализация.Товары.Количество > 0

| ТОГДА Реализация.Товары.Количество

| ИНАЧЕ 0

| КОНЕЦ) КАК КоличествоПозиций

|ИЗ

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

|ГДЕ

| Реализация.Дата МЕЖДУ &НачалоДня И &КонецДня

| И НЕ Реализация.ПометкаУдаления

|

|УПОРЯДОЧИТЬ ПО

| ДатаДокумента УБЫВ";

// 3. Устанавливаем параметры

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

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

// 4. Выполняем запрос

РезультатЗапроса = Запрос.Выполнить();

// 5. Формируем результат (например, таблицу значений)

ТаблицаРезультата = Новый ТаблицаЗначений;

ТаблицаРезультата.Колонки.Добавить("Ссылка");

ТаблицаРезультата.Колонки.Добавить("Дата");

ТаблицаРезультата.Колонки.Добавить("Сумма");

ТаблицаРезультата.Колонки.Добавить("КоличествоПозиций");

Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл

НоваяСтрока = ТаблицаРезультата.Добавить();

НоваяСтрока.Ссылка = Выборка.Ссылка;

НоваяСтрока.Дата = Выборка.ДатаДокумента;

НоваяСтрока.Сумма = Выборка.Сумма;

НоваяСтрока.КоличествоПозиций = Выборка.КоличествоПозиций;

КонецЦикла;

// 6. Выводим результат (например, в табличный документ)

Отчет = Новый ТабличныйДокумент;

Отчет.Очистить();

Макет = ПолучитьМакет("МакетОтчета");

Область = Макет.ПолучитьОбласть("Шапка");

Отчет.Вывести(Область);

Область = Макет.ПолучитьОбласть("Таблица");

Для Каждого Строка Из ТаблицаРезультата Цикл

Область.Параметры.Заполнить(Строка);

Отчет.Вывести(Область);

КонецЦикла;

Область = Макет.ПолучитьОбласть("Подвал");

Отчет.Вывести(Область);

Отчет.Показать("Отчет по продажам за " + Формат(ТекущаяДата, "ДФ=dd.MM.yyyy"));

КонецПроцедуры

Этот пример демонстрирует:

  • 📅 Корректную работу с границами дня
  • 🔍 Оптимизированный запрос с параметрами
  • 📊 Формирование читаемого отчета
  • 🖥️ Учет серверного времени

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

Часто задаваемые вопросы

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

В 1С 7.7 нет функции КонецДня(), но вы можете использовать следующий код:

Функция КонецДня1С7(ДатаНачало)

Возврат ДатаНачало + 86399/86400; // 86399 секунд = 23:59:59

КонецФункции

// Использование:

ДатаСКонцомДня = КонецДня1С7(ТекущаяДата());

Этот метод добавляет к дате 23 часа 59 минут и 59 секунд, что эквивалентно концу дня.

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

Наиболее вероятная причина — неверное использование оператора МЕЖДУ. Помните, что:

  • МЕЖДУ А И Б включает обе границы
  • Для конца дня нужно использовать Документ.Дата <= КонецДня вместо МЕЖДУ
  • Или использовать ДОБАВИТЬКДАТЕ(КонецДня, СЕКУНДА, -1) как верхнюю границу

Правильный вариант:

ГДЕ Документ.Дата >= НачалоДня И Документ.Дата <= КонецДня
Как учесть миллисекунды при ручном формировании конца дня?

Для учета миллисекунд добавьте к дате значение 0.999 (что соответствует 999 миллисекундам):

КонецДняСМиллисекундами = ДатаВремя(2026, 5, 15, 23, 59, 59) + 0.999;

Или используйте стандартную функцию:

КонецДняСМиллисекундами = КонецДня('20260515120000');

Функция КонецДня() автоматически устанавливает миллисекунды в 999.

Можно ли использовать КонецДня() для дат в формате строки?

Нет, сначала нужно преобразовать строку в дату. Пример:

ДатаСтрока = "15.05.2026";

Дата = Дата(ДатаСтрока); // Преобразуем строку в дату

КонецДня = КонецДня(Дата);

Если строка содержит и дату, и время (например, "15.05.2026 14:30:00"), используйте:

ДатаВремя = ДатаВремя(ДатаСтрока);

КонецДня = КонецДня(ДатаВремя);

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

В мобильном приложении доступны те же функции, что и в десктопной версии. Используйте: