В типовых конфигурациях 1С, таких как Бухгалтерия предприятия 3.0, дата самого документа отражает хозяйственную операцию, а не момент фактической записи объекта в информационную базу. Часто возникает задача выяснить, когда именно документ был создан физически. Разберем основные способы решения этой проблемы с помощью служебных механизмов платформы и конфигурации.
Платформа 1С использует стандарт UUID Version 1 (time-based). В таком идентификаторе заложено количество интервалов по 100 наносекунд, прошедших с момента перехода на григорианский календарь (15 октября 1582 года). Переставив шестнадцатеричные блоки строки идентификатора, мы можем вычислить исходную метку времени.
Рассмотрим программный алгоритм получения даты создания ссылки:
Функция ДатаСозданияСсылки(Ссылка) Экспорт
ГУИД = Строка(Ссылка.УникальныйИдентификатор());
// Проверим, что это UUID версии 1 (в третьей группе первым символом идет "1")
Если Сред(ГУИД, 15, 1) <> "1" Тогда
Возврат Неопределено;
КонецЕсли;
// Собираем шестнадцатеричное число времени из блоков идентификатора
Строка16 = Сред(ГУИД, 16, 3) + Сред(ГУИД, 10, 4) + Сред(ГУИД, 1, 8);
Разрядность = СтрДлина(Строка16);
ЧислоСек = 0;
Для Позиция = 1 По Разрядность Цикл
Символ = НРег(Сред(Строка16, Позиция, 1));
ЧислоСек = ЧислоСек + (Найти("123456789abcdef", Символ)) * Pow(16, Разрядность - Позиция);
КонецЦикла;
ЧислоСек = ЧислоСек / 10000000;
// Начало отсчета UUID v1 — 15 октября 1582 года в формате UTC
ДатаUTC = Дата(1582, 10, 15, 00, 00, 00) + ЧислоСек;
// Для получения локального времени добавляем смещение часового пояса сеанса
Возврат ДатаUTC + МестноеВремя(ТекущаяДатаСеанса()) - ТекущаяДатаСеанса();
КонецФункции
Проанализируем технические нюансы и ограничения данного метода:
УстановитьСсылкуНового() задолго до физической записи, время в УИД будет соответствовать моменту генерации ссылки.Самым надежным источником информации о первом появлении объекта является системный журнал регистрации платформы. Каждая первая запись документа фиксируется событием добавления данных.
Посмотрим на пример программной выборки первого события записи объекта:
Функция ПолучитьДатуСозданияИзЖР(Ссылка) Экспорт
Фильтр = Новый Структура;
Фильтр.Вставить("Данные", Ссылка);
Фильтр.Вставить("Событие", "_$Data$_.New"); // Событие создания нового объекта
ТаблицаЖР = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(ТаблицаЖР, Фильтр, "Дата, Пользователь, ИмяПользователя",, 1);
Если ТаблицаЖР.Количество() > 0 Тогда
Возврат ТаблицаЖР[0].Дата;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Важно учитывать: Журнал регистрации может регулярно сокращаться регламентными процедурами обслуживания для экономии дискового пространства. Если документ создан давно, записей о его создании в журнале может уже не остаться. Кроме того, выборка из больших файлов ЖР создает существенную нагрузку на сервер.
В конфигурации Бухгалтерия предприятия 3.0 присутствует встроенная подсистема версионирования. Если в разделе Администрирование — Общие настройки — История изменений включено версионирование для нужного вида документов, точные данные сохраняются в регистре сведений ВерсииОбъектов.
Разберем, как получить дату первой версии документа с помощью запроса:
Функция ПолучитьДатуПервойВерсии(Ссылка) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ВерсииОбъектов.ДатаВерсии КАК ДатаСоздания,
| ВерсииОбъектов.АвторВерсии КАК Автор
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
|ГДЕ
| ВерсииОбъектов.Объект = &Ссылка
|УПОРЯДОЧИТЬ ПО
| ВерсииОбъектов.НомерВерсии ВОЗР";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.ДатаСоздания;
КонецЕсли;
Возврат Неопределено;
КонецФункции
В платформе 1С, начиная с версии 8.3.11, появился встроенный механизм ИсторияДанных. Если для метаданных документа включено свойство ИсторияДанных, сведения о создании и модификации хранятся на уровне СУБД независимо от БСП.
Выясним дату создания через менеджер истории данных:
Функция ДатаСозданияПоИсторииДанных(Ссылка) Экспорт
История = ИсторияДанных.ПолучитьИсторию(Ссылка);
Если История.Количество() > 0 Тогда
// Самая ранняя версия находится в начале массива
Возврат История[0].Дата;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Если требуется гарантированно знать точный момент создания документов в будущем без обращения к тяжелым журналам и парсингу UUID, оптимально использовать расширение конфигурации. Добавим подписку на событие ПередЗаписью для требуемых документов:
Процедура Расш_ДокументыПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Источник.ЭтоНовый() Тогда
// Фиксируем системное время сеанса в дополнительный реквизит или независимый регистр
ТекущийМомент = ТекущаяДатаСеанса();
// Запись в реквизит или вызов процедуры фиксации даты
КонецЕсли;
КонецПроцедуры
Таким образом, для существующих документов в первую очередь следует проверить регистр ВерсииОбъектов и журнал регистрации. Если эти механизмы были отключены или очищены, вычисление даты из УИД остается единственным способом узнать приблизительное время создания объекта.