Разработка и Конфигурация · 11 мин
Как в 1С получить только время из даты
Как в 1С получить только время из даты: функции Час, Минута, Секунда, Формат, запросы и типовые ошибки. Примеры кода для конфигуратора и запросов.
Во встроенном языке 1С значение типа «Дата» всегда содержит и дату, и время с точностью до секунды. Отдельного типа «время без даты» в платформе нет, поэтому задача «получить только время» решается обходными способами: извлечением компонентов (часы, минуты, секунды), форматированием строки или вычислением смещения от начала дня.
Выбор способа зависит от контекста: нужен результат для вывода пользователю, для сравнения в запросе, для хранения в реквизите или для выгрузки во внешнюю систему. Ниже разобраны все рабочие варианты с примерами кода и типичными ошибками.
Как устроен тип «Дата» в 1С и почему времени отдельно нет
Тип «Дата» в 1С хранит момент времени с точностью до одной секунды: год, месяц, день, часы, минуты, секунды. Даже если вы указываете только календарную дату, время внутри значения равно 00:00:00. Именно поэтому «отрезать» время нельзя — можно только извлечь его составляющие или представить в нужном виде.
Это влияет и на проектирование конфигурации: если требуется хранить именно время (например, время начала смены), обычно выбирают один из трёх подходов — реквизит типа «Дата» с игнорируемой календарной частью, строковый реквизит формата «ЧЧ:ММ» или числовой реквизит (количество секунд от начала дня). Каждый вариант имеет ограничения, которые разобраны ниже.
Извлечение часов, минут и секунд функциями встроенного языка
Самый прямой способ — функции Час(), Минута() и Секунда(). Каждая принимает значение типа «Дата» и возвращает число: часы от 0 до 23, минуты и секунды от 0 до 59.
ДатаДокумента = ТекущаяДатаСеанса();
Ч = Час(ДатаДокумента); // например, 14
М = Минута(ДатаДокумента); // например, 5
С = Секунда(ДатаДокумента); // например, 30
Из этих чисел легко собрать строку нужного вида, дополнив значения ведущими нулями. Для этого удобна функция Формат() с форматной строкой для чисел:
ВремяСтрокой = Формат(Ч, "ЧЦ=2; ЧВН=") + ":"
+ Формат(М, "ЧЦ=2; ЧВН=") + ":"
+ Формат(С, "ЧЦ=2; ЧВН=");
// результат: "14:05:30"
Такой подход удобен, когда компоненты времени нужны по отдельности — например, для сравнения «событие произошло до 12:00» или для передачи часов и минут в разные поля внешней системы.
Получение времени строкой через функцию Формат()
Если время нужно только для отображения или выгрузки в файл, проще всего использовать Формат() с параметром локального формата даты.
ДатаДокумента = ТекущаяДатаСеанса();
ВремяКратко = Формат(ДатаДокумента, "ДЛФ=T"); // "14:05:30"
ВремяЧМ = Формат(ДатаДокумента, "ДФ=ЧЧ:мм"); // "14:05"
ВремяПолное = Формат(ДатаДокумента, "ДФ=ЧЧ:мм:сс"); // "14:05:30"
Разница между параметрами: ДЛФ=T выводит время в локальном формате (обычно ЧЧ:ММ:СС), а ДФ позволяет задать шаблон явно. В шаблоне ЧЧ — часы с ведущим нулём, мм — минуты, сс — секунды. Символы регистрозависимы: ММ в строке формата даты означает месяц, а мм — минуты, путать их нельзя.
Учтите, что результат Формат() — это строка. Сравнивать такие строки операторами «больше/меньше» можно только при фиксированной длине с ведущими нулями (ЧЧ:ММ:СС), иначе лексикографическое сравнение даст неверный результат.
Получение времени в запросах 1С
В языке запросов доступны одноимённые функции ЧАС(), МИНУТА() и СЕКУНДА(), которые применяются к полям типа «Дата»:
ВЫБРАТЬ
ЧАС(Регистрация.Период) КАК ЧасСобытия,
МИНУТА(Регистрация.Период) КАК МинутаСобытия
ИЗ
РегистрСведений.Регистрация КАК Регистрация
Типичный практический сценарий — выборка документов за определённый интервал времени внутри дня, например все продажи с 9:00 до 18:00 независимо от даты:
ВЫБРАТЬ
Продажи.Ссылка
ИЗ
Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
ЧАС(Продажи.Дата) >= 9
И ЧАС(Продажи.Дата) < 18
Здесь важно помнить о производительности: условие через функцию от поля не использует индекс по дате. На больших таблицах такой запрос приведёт к полному сканированию. Если выборки по времени выполняются регулярно, лучше хранить час или смещение от начала дня в отдельном индексированном реквизите и заполнять его при записи объекта.
Время как смещение от начала дня
Для сравнений и арифметики удобно представить время числом — количеством секунд, прошедших с начала дня. Получить его просто: вычесть из даты начало её же дня.
ДатаДокумента = ТекущаяДатаСеанса();
СекундОтНачалаДня = ДатаДокумента - НачалоДня(ДатаДокумента);
// число от 0 до 86399
Обратная операция — прибавить это число к любой дате, чтобы «перенести» время на другой день:
НоваяДата = НачалоДня(ДругаяДата) + СекундОтНачалаДня;
Этот приём незаменим, когда нужно сравнить два момента только по времени, игнорируя даты: достаточно сравнить два числа. Он же используется при хранении времени в числовом реквизите — один вариант проектирования, упомянутый выше.
Как хранить время в реквизитах: сравнение подходов
Поскольку отдельного типа для времени нет, при проектировании конфигурации приходится выбирать способ хранения. Ниже сопоставлены три основных варианта.
| Способ хранения | Плюсы | Ограничения |
|---|---|---|
| Дата (время с нулевой датой 01.01.0001) | Стандартный ввод, форматирование, арифметика дат | Легко случайно записать ненулевую дату; сортировка смешивается с датой |
| Число (секунды от начала дня) | Простое сравнение, компактный индекс | Нужна ручная конвертация для отображения; неочевидно для пользователя |
| Строка «ЧЧ:ММ» | Наглядно, просто выгружать | Нет валидации на уровне типа, ошибки сравнения, ручной контроль формата |
Что выбрать для хранения времени
Подходит, когда время — часть полноценного момента (дата и время документа). Для «чистого» времени требует дисциплины: всегда обнулять дату через НачалоДня().
Оптимально для сравнений, интервалов и индексированных поисков по времени. Требует функций конвертации для ввода и отображения.
Допустимо для простых справочников без вычислений. Для любой логики сравнения — худший вариант из-за отсутствия типизации.
Если используется реквизит типа «Дата» для хранения только времени, при записи принудительно обнуляйте календарную часть: Объект.ВремяНачала = НачалоДня(Объект.ВремяНачала) + СекундОтНачалаДня. Иначе в данных появятся разные даты, и сравнение значений сломается.
Типичные ошибки и их диагностика
Отдельно стоит сказать про часовые пояса. В клиент-серверном режиме ТекущаяДатаСеанса() возвращает время сеанса с учётом часового пояса сеанса, а устаревшее ТекущаяДата() на сервере — время сервера. Если пользователи работают в разных поясах, извлечённое время может отличаться от ожидаемого на несколько часов. Проверяйте, какое время реально записано в базу, прежде чем искать ошибку в форматировании.
Как проверить результат
Часы и минуты совпадают с исходной датой, минуты не равны номеру месяца
В позиции минут стоит номер месяца — ошибка в регистре букв формата
Результат сравнения не зависит от календарной части
Порядок меняется при смене даты — даты не обнулены
Выполняется быстро на рабочем объёме данных
Заметная задержка — условие не использует индекс, нужен отдельный реквизит
Краткий алгоритм выбора способа
Как выбрать способ
Что важно запомнить
В 1С нет отдельного типа «время»: используйте Час/Минута/Секунда для компонентов, Формат с ДФ=ЧЧ:мм:сс для строки, разность с НачалоДня() для арифметики. Следите за регистром букв в формате, обнулением даты и производительностью запросов с функциями.
Частые вопросы
Можно ли создать реквизит типа «время без даты» в конфигураторе?
Нет, такого типа в платформе не существует. Ближайший вариант — реквизит типа «Дата» с составом даты «Время»: в свойствах реквизита можно указать, что хранится только время. При этом физически дата остаётся равной 01.01.0001, а платформа сама ограничивает ввод и отображение временной частью. Это предпочтительный способ для реквизитов вроде «Время начала смены».
Как вывести время в формате 12 часов с AM/PM?
Стандартных символов AM/PM в форматной строке ДФ нет. Нужно вручную вычислить: взять Час(Дата), при необходимости вычесть 12, и добавить суффикс «AM» или «PM» в зависимости от значения часа. Обычно проще согласовать с пользователями 24-часовой формат.
Почему Формат(Дата, "ДФ=ЧЧ:мм") возвращает неправильные минуты?
Скорее всего, в форматной строке написаны прописные «ММ» — это месяц, а не минуты. Проверьте регистр: часы — «ЧЧ», минуты — строчные «мм», секунды — строчные «сс». Также убедитесь, что функция Формат вызывается в контексте, где доступна (на тонком клиенте она работает, но локальные форматы могут отличаться).
Как сравнить два документа только по времени, игнорируя дату?
Переведите оба значения в секунды от начала дня: Дата1 - НачалоДня(Дата1) и Дата2 - НачалоДня(Дата2), затем сравните полученные числа. Сравнивать напрямую значения типа «Дата» нельзя — в них участвует и календарная часть.
Как получить время из даты в СКД или динамическом списке?
В тексте запроса используйте функции ЧАС(), МИНУТА(), СЕКУНДА() — они доступны в выражениях СКД так же, как в обычных запросах. Для отображения строкой добавьте вычисляемое поле и формируйте строку в коде при выводе, либо используйте формат поля в настройках компоновки.
Влияет ли часовой пояс на извлекаемое время?
Да. Функции Час(), Минута(), Секунда() возвращают компоненты того значения даты, которое им передано. Если значение записано в одном поясе, а читается в сеансе с другим поясом, отображаемое время может различаться. Для единообразия используйте ТекущаяДатаСеанса() и при необходимости явно храните часовой пояс данных.