Разработка и Конфигурация · 8 мин
Как отсечь время от даты в 1С
Как отсечь время от даты в 1С: НачалоДня, форматная строка, запросы и типовые ошибки. Практические примеры кода для разработчика и пользователя 1С.
В 1С тип «Дата» всегда хранит и день, и время с точностью до секунды. Даже если пользователь ввёл только «12.03.2026», внутри значение выглядит как «12.03.2026 0:00:00». Поэтому сравнение двух дат напрямую часто даёт неожиданный результат: документ от 12.03.2026 14:35:21 не равен дате 12.03.2026 0:00:00, хотя визуально это один и тот же день.
Задача «отсечь время» возникает постоянно: при отборах в отчётах, при сравнении дат документов, при группировке данных за день в запросах, при обмене данными с внешними системами. Способов несколько — от встроенных функций языка до функций языка запросов, и у каждого свои границы применения.
Ниже разобраны основные приёмы: функция НачалоДня(), приведение через форматную строку, функции НАЧАЛОПЕРИОДА и ДАТАВРЕМЯ в запросах, а также типовые ошибки, которые приводят к «потерянным» документам в отчётах.
Почему в 1С дата всегда содержит время
Тип «Дата» во встроенном языке 1С — это единое значение «дата и время». Отдельного типа «только день» в платформе нет. Когда реквизит документа имеет состав даты «Дата», платформа просто обнуляет время при вводе, но физически хранится всё равно полное значение.
Из-за этого возникают типичные проблемы. Сравнение Документ.Дата = '20260312' не найдёт документ, проведённый в 14:35. Отбор в динамическом списке «за сегодня» без учёта времени покажет только записи с нулевым временем. Группировка в запросе по полю «Дата» разобьёт один день на множество строк — по числу различных значений времени.
Функция НачалоДня() — основной способ в коде
Самый правильный способ отсечь время во встроенном языке — функция НачалоДня(). Она принимает дату и возвращает ту же дату с временем 0:00:00:
ДатаДокумента = ДокументОбъект.Дата; // 12.03.2026 14:35:21
ДатаБезВремени = НачалоДня(ДатаДокумента); // 12.03.2026 0:00:00
Если НачалоДня(ДатаДокумента) = НачалоДня(ТекущаяДатаСеанса()) Тогда
// документ от сегодняшнего дня
КонецЕсли;
Рядом работают родственные функции: КонецДня() возвращает 23:59:59 того же дня, НачалоМесяца(), НачалоКвартала(), НачалоГода(), НачалоНедели() — начало соответствующего периода. Пара НачалоДня/КонецДня особенно удобна для отборов за один день:
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаОтбора));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОтбора));
Отсечение времени в запросах: НАЧАЛОПЕРИОДА
В языке запросов своя функция — НАЧАЛОПЕРИОДА(Дата, Период). Для отсечения времени используется период ДЕНЬ:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Продажи.Период, ДЕНЬ) КАК День,
СУММА(Продажи.СуммаОборот) КАК Сумма
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(Продажи.Период, ДЕНЬ)
Такая группировка собирает все движения внутри суток в одну строку независимо от времени. Это стандартный приём для отчётов «по дням». Аналогично можно группировать по НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД.
Для сравнения дат в условии ГДЕ тоже лучше использовать НАЧАЛОПЕРИОДА, а не приведение к строке: функция работает с индексами и не ломает оптимизацию запроса, в отличие от преобразований через ПОДСТРОКА.
Форматная строка: когда нужно только показать дату
Если задача — не сравнить, а вывести дату без времени пользователю, достаточно функции Формат():
СтрокаДаты = Формат(ДатаДокумента, "ДЛФ=D"); // "12.03.2026"
СтрокаДаты = Формат(ДатаДокумента, "ДФ='dd.MM.yyyy'"); // то же самое явно
Ключевое ограничение: Формат() возвращает строку, а не дату. Сравнивать такие строки как даты нельзя — строковое сравнение «31.12.2026» и «01.01.2026» даст неверный порядок, если сравнивать лексикографически в другом формате. Для логики и отборов используйте НачалоДня, а Формат оставьте для представления в сообщениях, печатных формах и наименованиях.
В формах и отчётах на СКД формат даты обычно задаётся декларативно: у поля есть свойство «Формат», где достаточно указать ДЛФ=D — тогда время не отображается без всякого кода.
Сравнение способов
Код модулей, сравнения, параметры запросов. Возвращает дату — подходит для логики.
Группировки и условия внутри запроса. Не работает вне языка запросов.
Только вывод пользователю. Возвращает строку, не годится для сравнений.
Предотвращение проблемы: в свойствах реквизита установить «Дата», тогда время не вводится вовсе.
Профилактика: состав даты у реквизитов
Часто время «появляется» потому, что у реквизита в конфигураторе состав даты установлен как «Дата и время». Если бизнес-смысл поля — только день (дата рождения, дата договора, дата поставки), правильнее исправить метаданные: в свойствах реквизита установить «Состав даты» = «Дата». Тогда платформа сама обнуляет время при записи, и отсекать его в коде не придётся.
Менять состав даты у существующего реквизита, в котором уже есть данные со временем, нужно осторожно: при реструктуризации время будет отброшено безвозвратно. Перед изменением сделайте резервную копию информационной базы и проверьте, не используется ли время этого поля в каких-либо алгоритмах.
Типовые ошибки и как их проверить
Самая частая ошибка — сравнение даты документа с датой-константой без приведения: Если Док.Дата = '20260312' Тогда. Литерал имеет нулевое время, документ — реальное, равенства нет. Вторая ошибка — отбор «с 01.03 по 31.03», где конец периода задан как 31.03 0:00:00: весь день 31 марта выпадает из выборки. Правильно — использовать КонецДня() или Границу с видом «Включая».
Третья ошибка — отсечение времени через строковые преобразования в запросе (ПОДСТРОКА от представления даты). Это медленно, зависит от региональных настроек сервера и ломается при смене формата. Используйте НАЧАЛОПЕРИОДА.
Как проверить результат
НачалоДня(Дата1) = НачалоДня(Дата2) возвращает Истина
Равенство Ложь при визуально одинаковом дне — время не отсечено
В выборку попадают документы с любым временем этого дня
Попадают только записи с временем 0:00:00
Одна строка на календарный день
Несколько строк на один день с разным временем
FAQ
Чем НачалоДня отличается от ДатаВремя с нулевым временем?
Результат одинаков — дата с временем 0:00:00. Но НачалоДня читаемее и не требует вручную собирать дату через Дата(Год, Месяц, День). В запросах аналог — НАЧАЛОПЕРИОДА, а конструктор ДАТАВРЕМЯ(Год, Месяц, День) тоже даёт нулевое время.
Как получить конец дня для отбора?
Используйте КонецДня(Дата) — возвращает 23:59:59. Либо в запросе передайте границу: Новый Граница(КонецДня(Дата), ВидГраницы.Включая). Просто НачалоДня последнего дня в качестве конца периода — ошибка: весь день выпадет из выборки.
Можно ли отсечь время в СКД без изменения запроса?
Да. В настройках СКД у поля даты можно задать формат ДЛФ=D для отображения, а для группировки по дням использовать в запросе вычисляемое поле с НАЧАЛОПЕРИОДА или встроенные периодичности при работе с виртуальными таблицами регистров.
Почему сравнение дат даёт Ложь, хотя день одинаковый?
Потому что сравниваются полные значения «дата + время». Документ в 14:35 не равен дате-константе с нулевым временем. Оберните обе стороны в НачалоДня() — тогда сравнение идёт по календарному дню.
Как отсечь время при обмене данными с внешней системой?
При выгрузке в XML/JSON дату обычно преобразуют в строку нужного формата через Формат() или ЗаписатьДатуJSON с вариантом ISO. Если внешняя система ждёт только день, формируйте строку вида «2026-03-12» явно, а не полагайтесь на сериализацию по умолчанию — она включает время.
Что важно запомнить
В коде — НачалоДня(), в запросах — НАЧАЛОПЕРИОДА(Дата, ДЕНЬ), для вывода — Формат с ДЛФ=D. Для отборов за день используйте пару НачалоДня/КонецДня. Если время не нужно в принципе — настройте состав даты реквизита в конфигураторе.