Как определить дату создания элемента справочника по его ГУИД и вывести данные в отчет на СКД

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

В практике разработчика 1С часто возникает задача узнать дату создания того или иного объекта (справочника или документа), когда специализированные реквизиты для этого не были предусмотрены заранее. Одним из "магических" способов является извлечение этой информации из уникального идентификатора (GUID). В рамках данной статьи мы подробно разберем, как реализовать этот метод, внедрим его в Систему компоновки данных (СКД), выясним, почему он может ошибаться, и рассмотрим более надежные современные альтернативы.

Метод извлечения даты из ГУИД: как это работает

Для начала разберем техническую сторону вопроса. Уникальный идентификатор (GUID) в 1С версии 8 представляет собой 128-битное число. Если объект создается средствами платформы (а не генерируется внешними системами как случайный набор знаков), он обычно соответствует стандарту UUID версии 1. Этот стандарт базируется на текущем времени (количестве 100-наносекундных интервалов с момента принятия григорианского календаря — 15 октября 1582 года) и MAC-адресе сетевой карты.

Однако есть нюанс: 1С и Microsoft SQL Server хранят байты идентификатора в "перепутанном" виде. Чтобы получить дату, нам нужно переставить сегменты строки ГУИД в правильном порядке. Рассмотрим программный код, который выполняет эту операцию:


Функция ПолучитьДатуСозданияИзГКИД(Ссылка) Экспорт
    Если Ссылка.Пустая() Тогда
        Возврат Дата(1, 1, 1);
    КонецЕсли;

    ГУИД = Строка(Ссылка.УникальныйИдентификатор());
    // Убираем дефисы для удобства манипуляций
    ГУИД = СтрЗаменить(ГУИД, "-", "");
    
    // Переставляем части ГУИД в соответствии с алгоритмом хранения времени
    // Нам нужны сегменты, отвечающие за TimeLow, TimeMid и TimeHigh
    Строка16 = Сред(ГУИД, 13, 3) + Сред(ГУИД, 9, 4) + Сред(ГУИД, 1, 8);
    
    Разрядность = СтрДлина(Строка16);
    ЧислоСек = 0;
    
    // Переводим из 16-ричной системы в 10-тичную
    Для Позиция = 1 По Разрядность Цикл
        Символ = Сред(Строка16, Позиция, 1);
        ЧислоСек = ЧислоСек + (Найти("0123456789abcdef", Символ) - 1) * Pow(16, Разрядность - Позиция);
    КонецЦикла;
    
    // Вычисляем количество секунд (делим на 10 000 000 для перевода из 100-наносекундных интервалов)
    ЧислоСек = ЧислоСек / 10000000;
    
    // Добавляем полученное время к базовой дате (с учетом смещения часового пояса, если нужно)
    Возврат Дата(1582, 10, 15, 04, 00, 00) + ЧислоСек;
КонецФункции

Важный момент: в коде выше используется смещение 4 часа Дата(1582, 10, 15, 04, 00, 00). Это связано с часовым поясом. Если ваши серверы работают в другом поясе, константу времени в базовой дате придется скорректировать.

Интеграция функции в отчет СКД

Чтобы использовать этот алгоритм в отчете, выполним следующие шаги:

  1. Создадим Общий модуль (например, СервисОбъектов), установим ему свойства Сервер, Внешнее соединение и обязательно флаг Вызов сервера.
  2. Поместим нашу функцию ПолучитьДатуСозданияИзГКИД в этот модуль с ключевым словом Экспорт.
  3. Откроем схему компоновки данных нашего отчета. Перейдем на закладку Вычисляемые поля.
  4. Добавим новое поле:
    • Путь к данным: ДатаСоздания
    • Выражение: СервисОбъектов.ПолучитьДатуСозданияИзГКИД(Ссылка)
    • Заголовок: Дата создания (из GUID)

После этого поле ДатаСоздания станет доступно в настройках отчета на вкладке "Выбранные поля" и "Отбор".

Реализация фильтра "За сегодня"

Проанализируем ситуацию, когда нам нужно вывести номенклатуру, созданную именно сегодня. Так как дата вычисляется программно в функции, мы не можем использовать ее в секции ГДЕ основного запроса (СУБД ничего не знает о нашей функции 1С).

Рассмотрим порядок настройки фильтра в СКД:

  1. Переходим на вкладку Настройки.
  2. Выбираем вкладку Отбор.
  3. Добавляем новый элемент отбора, выбираем наше вычисляемое поле ДатаСоздания.
  4. Вид сравнения устанавливаем Больше или равно.
  5. В поле значения выбираем Использование параметра или просто указываем НачалоПериода(&ТекущаяДата, "День"), если компоновка позволяет использовать выражения в значениях.

Внимание: Использование функций в вычисляемых полях СКД для больших объемов данных (например, справочник номенклатуры на 500 000 позиций) приведет к существенному замедлению отчета. Платформа будет вынуждена получить все ссылки из БД, а затем для каждой строки последовательно вызывать код на языке 1С.

Почему метод может выдавать "даты из будущего" (например, 2056 год)?

Выясним причину, по которой автор исходной темы столкнулся с некорректными результатами. Это происходит по трем причинам:

Более надежные альтернативы

Если вам требуется юридически значимая или технически точная дата создания, рассмотрим профессиональные архитектурные подходы:

1. Использование механизма "История данных"

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

2. Общий реквизит "Дата создания"

Проанализируем самый эффективный способ с точки зрения производительности:

  1. Создаем в конфигурации Общий реквизит с именем ДатаСоздания (тип Дата).
  2. В свойствах указываем Автоиспользование: Использовать для нужных справочников.
  3. Создаем Подписку на событие ПередЗаписью для типа СправочникОбъект.
  4. В обработчике пишем:

Процедура ПриЗаписиОбъектаПередЗаписью(Источник, Отказ) Экспорт
    Если Источник.ЭтоНовый() Тогда
        Источник.ДатаСоздания = ТекущаяДатаСеанса();
    КонецЕсли;
КонецПроцедуры

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

3. Подсистема "Версионирование объектов" из БСП

Если ваша конфигурация использует Библиотеку стандартных подсистем (БСП), рекомендуется включить версионирование для нужных справочников. Дата самой первой версии объекта и будет являться датой его создания. Эти данные хранятся в регистре сведений ВерсииОбъектов.

Подведем итог: Метод с ГУИД — это отличное "хакерское" решение для разового анализа данных в базе, где не велись логи. Однако для постоянного использования в отчетах лучше внедрить общий реквизит или использовать историю данных платформы.

← На главную