Работа с датами в 1С:Предприятие — одна из самых частых задач, с которыми сталкиваются разработчики и пользователи. Особенно актуальна проблема приведения даты к концу дня: это требуется для корректного формирования отчетов, расчета сроков, фильтрации данных и многих других операций. Например, если вам нужно получить все документы за текущий день до 23:59:59, или рассчитать пени по договору с учетом полного рабочего дня.
В этой статье мы разберем 5 рабочих способов привести дату к концу дня в 1С 8.3 и 8.2, включая встроенные функции платформы, программные решения на встроенном языке и нюансы работы с временными зонами. Каждый метод проиллюстрирован практическими примерами кода, которые вы сможете сразу использовать в своих конфигурациях. Особое внимание уделим типичным ошибкам и способам их избежать.
Материал будет полезен как начинающим разработчикам 1С, так и опытным специалистам, которые хотят оптимизировать свой код. Все примеры протестированы на актуальных версиях платформы и совместимы с большинством типовых конфигураций (Бухгалтерия 3.0, УТ 11, ЗУП 3.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. Работа с временными зонами и серверным временем
При работе в распределенных системах или с удаленными базами данных важно учитывать временные зоны. Функция КонецДня() использует текущие настройки временной зоны системы, что может привести к неожиданным результатам, если сервер и клиент находятся в разных часовых поясах.
Основные сценарии:
- 🌍 Клиент и сервер 1С в разных временных зонах
- ☁️ Облачные решения (1C:Fresh, 1C:Линк)
- 🖥️ Распределенные информационные базы
Для корректной работы используйте:
// Получение текущей даты на сервере с учетом его временной зоны
СервернаяДата = ТекущаяДатаСеанса();
КонецДняНаСервере = КонецДня(СервернаяДата);
// Если нужно привести к концу дня в конкретной временной зоне
ВременнаяЗона = Новый Структура("ЧасовойПояс, ЛетнееВремя", 3, Истина); // UTC+3 с летним временем
КонецДняВЗоне = КонецДня(ТекущаяДата()) + ВременнаяЗона.ЧасовойПояс*3600;
Как проверить текущую временную зону сервера?
Используйте код Сообщить(ТекущаяВременнаяЗона()) — это покажет смещение в часах относительно UTC и статус летнего времени.
Типичные ошибки при работе с временными зонами:
- Игнорирование разницы между клиентским и серверным временем
- Неучет переходов на зимнее/летнее время при ручных расчетах
- Использование
ТекущаяДата()вместоТекущаяДатаСеанса()в серверных процедурах
Всегда используйте ТекущаяДатаСеанса() в серверных процедурах, если важна точность по времени сервера, а не клиента.
4. Приведение даты к концу дня в запросах 1С
Особый случай — работа с датами непосредственно в запросах 1С. Здесь нельзя использовать функцию КонецДня() напрямую, но есть несколько эффективных альтернатив.
Основные подходы:
Способ 1: Использование конструкции ДОБАВИТЬКДАТЕ()
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка
ИЗ
Документ.ЗаказКлиента КАК Документ
ГДЕ
Документ.Дата МЕЖДУ &НачалоДня И ДОБАВИТЬКДАТЕ(&КонецДня, СЕКУНДА, -1)
Способ 2: Формирование границ дня в параметрах
НачалоДня = НачалоДня(&ДатаОтчета);
КонецДня = КонецДня(&ДатаОтчета);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Документ.Ссылка КАК Ссылка,
| Документ.СуммаДокумента КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Документ
|ГДЕ
| Документ.Дата >= &НачалоДня
| И Документ.Дата <= &КонецДня";
Запрос.УстановитьПараметр("НачалоДня", НачалоДня);
Запрос.УстановитьПараметр("КонецДня", КонецДня);
Важные нюансы:
- 🔍 В запросах 1С оператор
МЕЖДУвключает обе границы, поэтому для конца дня нужно указыватьДОБАВИТЬКДАТЕ(..., СЕКУНДА, -1) - 📋 При использовании параметров запрос может быть оптимизирован системой
- ⚡ Для больших баз данных предварительное вычисление границ дня в коде работает быстрее, чем расчет в самом запросе
Вычислили начало и конец дня ДО формирования запроса|
Использовали параметры вместо прямой вставки значений|
Проверили включение/исключение границ в условиях|
Учли временные зоны при работе с распределенными базами
-->
5. Особенности работы с датами в типовых конфигурациях
Типовые конфигурации 1С (Бухгалтерия 3.0, УТ 11, ЗУП 3.1) часто имеют свои нюансы работы с датами. Рассмотрим наиболее распространенные сценарии, где требуется приведение даты к концу дня.
Бухгалтерия 3.0:
- 💰 Расчет пеней по налогам — конец дня используется для определения последнего дня уплаты
- 📑 Формирование регламентных отчетов — фильтрация документов за полный день
- 🔄 Закрытие месяца — операции проводятся на конец последнего дня периода
Управление торговлей 11:
- 📦 Отчеты по продажам — анализ выручки за полный рабочий день
- 🚚 Контроль отгрузок — фиксация времени завершения отгрузки
- 📈 ABC/XYZ-анализ — сегментация данных по полным дням
Зарплата и Управление Персоналом 3.1:
- 💳 Расчет зарплаты — учет отработанного времени до конца дня
- 📅 Табели учета рабочего времени — фиксация выходов/уходов
- 🎁 Начисление премий — привязка к полным отчетным периодам
Пример из Бухгалтерии 3.0 для расчета пеней:
// Расчет пеней за просрочку платежа
ДатаПлатежа = Документ.ДатаОплаты;
ТекущаяДата = ТекущаяДата();
ДниПросрочки = (КонецДня(ТекущаяДата) - КонецДня(ДатаПлатежа)) / 86400;
СуммаПеней = СуммаДолга СтавкаПеней ДниПросрочки / 100;
⚠️ Внимание: В ЗУП 3.1 при работе с табелями учета рабочего времени функция КонецДня() может давать неожиданные результаты для ночных смен. В таких случаях используйте ручное формирование даты с учетом специфики графика работы.
6. Типичные ошибки и как их избежать
Даже опытные разработчики 1С иногда допускают ошибки при работе с приведением дат к концу дня. Рассмотрим наиболее распространенные проблемы и способы их решения.
Ошибка 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С?
В мобильном приложении 1С доступны те же функции, что и в десктопной версии. Используйте: