Как программно определить, что хранится в переменной типа Дата: дата, время или дата и время?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Техническая суть типа данных Дата в 1С:Предприятие

Для начала проанализируем, как платформа 1С работает с датами на системном уровне. В «1С:Предприятие 8» тип данных Дата является простым примитивным типом. Физически в оперативной памяти и в СУБД этот тип всегда хранит одновременно и дату, и время с точностью до одной секунды. На уровне базы данных это число секунд, прошедших с 1 января 0001 года.

По этой причине в кодовой переменной физически не может существовать значения, которое содержало бы «только время» без даты или «только дату» без времени. Платформа всегда подставит значения по умолчанию для недостающих частей:

Из-за этой технической особенности стандартная проверка типа через функцию ТипЗнч() всегда будет возвращать просто тип Дата, не давая нам информации о ее семантическом составе. Однако мы можем обойти это ограничение, используя системные соглашения платформы.

Программный метод определения состава даты в переменной

Разберем по шагам логику, которая позволит нам программно определить, что именно хранится в переменной. Мы построим наш алгоритм на сравнении исследуемой переменной с ее «началом дня» и пустой датой.

Рассмотрим готовую функцию, которую вы можете использовать в своих проектах:


Функция ОпределитьСоставДаты(ЗначениеДаты) Экспорт
    
    // Шаг 1. Проверяем на пустую дату
    Если Не ЗначениеЗаполнено(ЗначениеДаты) Тогда
        Возврат "ПустаяДата";
    КонецЕсли;
    
     НачалоСуток = НачалоДня(ЗначениеДаты);
    
    // Шаг 2. Проверяем, хранится ли в переменной ТОЛЬКО время
    // Если дата указывает на начало времен (01.01.0001), но время заполнено
    Если НачалоСуток = '00010101' И ЗначениеДаты <> '00010101' Тогда
        Возврат "ТолькоВремя";
    КонецЕсли;
    
    // Шаг 3. Проверяем, хранится ли в переменной ТОЛЬКО дата
    // Если время равно 00:00:00, то значение совпадает с началом своего дня
    Если ЗначениеДаты = НачалоСуток И ЗначениеДаты <> '00010101' Тогда
        Возврат "ТолькоДата";
    КонецЕсли;
    
    // Шаг 4. Если предыдущие проверки не сработали — у нас заполнены оба компонента
    Возврат "ДатаИВремя";
    
КонецФункции

Проанализируем работу этой функции подробнее:

  1. Проверка на пустоту: С помощью функции Не ЗначениеЗаполнено() мы сразу отсекаем пустую дату. Если переменная равна '00010101000000', мы понимаем, что никаких полезных данных в ней нет.
  2. Проверка «Только Время»: Если в переменной лежит только время, то ее дата автоматически сброшена в 01.01.0001. Мы берем начало дня от нашей переменной. Если оно равно 01.01.0001, но сама переменная при этом не пустая, значит, в переменной содержится только время (например, 14:30:15).
  3. Проверка «Только Дата»: Если в переменной сохранена только дата, время автоматически равно 00:00:00. Это значит, что сама переменная абсолютно идентична результату функции НачалоДня(ЗначениеДаты). Если это равенство соблюдается (и дата не пустая), мы имеем дело с чистой датой.
  4. Проверка «Дата и Время»: Если переменная не пустая, время не равно полночи (или дата не равна 1 января 1 года), значит, в ней содержатся значащие компоненты и даты, и времени.

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

Влияние свойства «ЧастиДаты» в метаданных и на форме

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

Свойство ЧастиДаты (DateParts) настраивается в конфигураторе для реквизитов объектов (справочников, документов) и определяет два ключевых момента:

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


// Пример проверки настройки реквизита "ДатаРождения" у справочника "ФизическиеЛица"
СвойстваРеквизита = Метаданные.Справочники.ФизическиеЛица.Реквизиты.ДатаРождения.Тип;
// Получаем допустимые типы описания
ОписаниеТиповДаты = СвойстваРеквизита.ПривестиЗначение('00010101');

Для более детального анализа маски ввода конкретного элемента на форме можно использовать свойства поля формы, такие как Формат или непосредственно тип связанного с ним реквизита.

Особенности работы с частями дат в запросах 1С

При написании запросов разработчики также часто сталкиваются с необходимостью отсекать или сравнивать отдельные части дат. Рассмотрим несколько практических приемов.

Чтобы получить пустую дату в запросе, мы не можем использовать пустые литералы, как в коде. Вместо этого применяется специальная функция ДАТАВРЕМЯ:


ВЫБРАТЬ
    Ссылка,
    ДатаРождения
ИЗ
    Справочник.ФизическиеЛица
ГДЕ
    ДатаРождения <> ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)

Если в базе данных хранится реквизит со значением «Только время» (дата в нем равна 01.01.0001), попытка сравнить его напрямую с текущей датой (например, через ТекущаяДата()) приведет к некорректным результатам, так как текущая дата всегда будет больше.

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


ВЫБРАТЬ
    РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ПланыРабот.ВремяНачала, ДЕНЬ), ПланыРабот.ВремяНачала, СЕКУНДА) КАК СекундСНачалаДня
ИЗ
    РегистрСведений.ПланыРабот КАК ПланыРабот

Этот прием позволяет сравнивать временные интервалы без привязки к конкретному календарному дню.

Развитие экосистемы 1С: современный тип «ДатаВремя»

Платформа 1С не стоит на месте, и в современных технологиях экосистемы (таких как среда разработки «1С:Элемент» и язык сценариев «1С:Исполнитель») подход к работе с временными типами данных был существенно переработан и улучшен.

В этих новых технологиях классический тип данных Дата уступил место более строгому и международному типу ДатаВремя:

Несмотря на это, при работе в классической платформе «1С:Предприятие 8» знание внутренних механизмов хранения дат и умение использовать эвристические проверки остаются базовыми и необходимыми навыками для любого профессионального разработчика.

← На главную