Как преобразовать Unix Timestamp миллисекунды в дату 1С при интеграции с REST API эквайринга Сбербанка

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

При интеграции платформы 1С:Предприятие с внешними платежными шлюзами, в частности с REST API эквайринга Сбербанка, разработчики часто сталкиваются с тем, что даты транзакций, регистрации заказов и проведения платежей возвращаются в непривычном формате. Вместо стандартной строки даты шлюз присылает длинное числовое значение, например 1554091557065. Это значение представляет собой временную метку Unix Timestamp, выраженную в миллисекундах.

В рамках этой статьи мы подробно разберем, как правильно работать с такими данными в 1С. Мы проанализируем популярные ошибки разработчиков при ручной конвертации, рассмотрим правильный математический алгоритм преобразования, а также внедрим передовые практики автоматического восстановления дат в процессе десериализации JSON-пакетов средствами платформы 1С:Предприятие 8.3.

В чем суть проблемы и что такое Unix Timestamp в миллисекундах

Стандартное время Unix (POSIX time) — это система описания моментов времени, определяемая как количество секунд, прошедших с полуночи (00:00:00 UTC) 1 января 1970 года (эпоха Unix). Однако современные веб-сервисы, ориентированные на высокую точность и построенные на технологиях JavaScript/Java (включая API Сбербанка), используют более точную метрику — миллисекунды с начала эпохи Unix.

Число 1554091557065 состоит из 13 цифр:

  1. Первые 10 цифр (1554091557) — это стандартное Unix-время в секундах, соответствующее дате 01.04.2019 04:05:57 UTC.
  2. Последние 3 цифры (065) — это миллисекунды.

Если попытаться обработать это значение стандартными методами 1С напрямую, мы неизбежно столкнемся с ошибками позиционирования во времени. Разберем типичное ошибочное решение, которое часто встречается на форумах.

Разбор критической ошибки ручного преобразования

Начинающие разработчики часто пытаются применить простую арифметику дат в 1С. В платформе прибавление числа к переменной типа Дата трактуется как добавление указанного количества секунд. Из-за этого возникает соблазн написать следующий код:


Функция СконвертироватьВремяUnixTS(UnixTime) 
    // ОШИБОЧНЫЙ КОД!
    Возврат МестноеВремя('19700101' + UnixTime); 
КонецФункции

Выясним причину, почему этот код вернет некорректный результат. Если мы передадим в эту функцию число 1554091557065, платформа попытается прибавить к базовой дате 1 января 1970 года более полутора триллионов секунд. В результате нехитрых математических расчетов мы получим дату в районе 49279 года. Очевидно, что такое поведение программы является грубой логической ошибкой.

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

Способ 1. Правильная математическая конвертация вручную

Рассмотрим по шагам правильный алгоритм ручной конвертации. Нам необходимо выполнить следующие действия:

  1. Привести входящее значение к числовому типу данных.
  2. Разделить полученное число на 1000, чтобы избавиться от миллисекунд и получить чистые секунды.
  3. Отбросить дробную часть (миллисекунды) с помощью функции Цел(), так как стандартный тип данных Дата в 1С не поддерживает хранение миллисекунд.
  4. Прибавить полученное число секунд к базовой дате начала эпохи Unix — '19700101000000'.

Посмотрим на практический пример реализации такой функции на языке программирования 1С:


// Функция преобразует Unix Timestamp (миллисекунды) в стандартную дату 1С
// Параметры:
//  UnixTimeMillisecond - Число или Строка - временная метка от Сбербанка
// Возвращаемое значение:
//  Дата (UTC)
Функция ПреобразоватьUnixMillisВДату1С(Знач UnixTimeMillisecond) Экспорт

    Если Не ЗначениеЗаполнено(UnixTimeMillisecond) Тогда
        Возврат '00010101000000';
    КонецЕсли;
    
    Попытка
        Число Milliseconds = Число(UnixTimeMillisecond);
    Исключение
        ЗаписьЖурналаРегистрации("ИнтеграцияСбербанк.ОшибкаКонвертацииДаты",
            УровеньЖурналаРегистрации.Ошибка, , ,
            "Не удалось привести значение к числу: " + UnixTimeMillisecond);
        Возврат '00010101000000';
    КонецПопытки;
    
    // Переводим миллисекунды в секунды
    ЧислоСекунд = Цел(ЧислоMilliseconds / 1000);
    
    // Прибавляем секунды к начальной точке отсчета (в формате UTC)
    ДатаUTC = '19700101000000' + ЧислоСекунд;
    
    Возврат ДатаUTC;

КонецФункции

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

Способ 2. Использование встроенных механизмов чтения JSON (Best Practice)

Начиная с версии платформы 1С:Предприятие 8.3.6, разработчикам доступен объект ЧтениеJSON, который позволяет гибко управлять процессом десериализации данных. Вместо того чтобы обходить полученное дерево соответствий и вручную конвертировать каждое числовое поле с датой, мы можем задействовать специальный механизм — функцию восстановления дат.

Для этого мы преобразуем числовое представление Unix Timestamp в строку формата даты JavaScript прямо «на лету» в процессе чтения JSON-пакета, а затем вызовем встроенную функцию платформы ПрочитатьДатуJSON.

Разберем по шагам, как настроить этот процесс в коде:


// Основной метод, выполняющий чтение ответа от Сбербанка
Процедура РазобратьОтветЭквайринга(СтрокаОтветаСбера)
    
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(СтрокаОтветаСбера);
    
    // В параметрах ПрочитатьJSON указываем имя функции восстановления,
    // которая будет вызываться для каждого свойства десериализуемого объекта
    ДанныеОтвета = ПрочитатьJSON(Чтение, Ложь, , , "ВосстановитьДатыСбербанка", ЭтотОбъект);
    Чтение.Закрыть();
    
    // На выходе в структуре ДанныеОтвета поля дат будут содержать полноценный тип Дата 1С
    Если ДанныеОтвета.Свойство("createdDate") Тогда
        ЗаписатьДатуВБазу(ДанныеОтвета.createdDate);
    КонецЕсли;

КонецПроцедуры

// Функция восстановления, вызываемая платформой автоматически.
// Должна быть объявлена с ключевым словом Экспорт.
Функция ВосстановитьДатыСбербанка(Свойство, Значение, ДополнительныеПараметры) Экспорт
    
    // Определяем перечень полей Сбербанка, содержащих временные метки.
    // Обычно это поля "date", "createdDate", "registerDate", "paymentDate" и т.д.
    Если Свойство = "date" 
        Или Свойство = "createdDate" 
        Или Свойство = "registerDate" 
        Или Свойство = "paymentDate" Тогда
        
        Если ТипЗнч(Значение) = Тип("Число") И Значение > 0 Тогда
            // Формируем строковое представление инициализации даты в JavaScript.
            // Пример: "new Date(1554091557065)"
            СтрокаJS = "new Date(" + Формат(Значение, "ЧГ=") + ")";
            
            // Читаем дату с использованием платформенного формата JavaScript
            Возврат ПрочитатьДатуJSON(СтрокаJS, ФорматДатыJSON.JavaScript);
        КонецЕсли;
        
    КонецЕсли;
    
    // Все остальные поля возвращаем без изменений
    Возврат Значение;
    
КонецФункции

Использование функции восстановления дат — это наиболее правильный подход с точки зрения стандартов разработки фирмы «1С». Это упрощает код, избавляет от необходимости пост-обработки структуры данных и снижает вероятность пропуска полей, требующих конвертации.

Нюансы работы с часовыми поясами (UTC против Местного времени)

Проанализируем важный аспект интеграции, связанный с географическим распределением серверов и часовыми поясами. Все временные метки, передаваемые через REST API Сбербанка, зафиксированы в часовом поясе UTC (Всемирное координированное время).

Когда мы получаем дату из Unix Timestamp с помощью сложения с базовой датой или через ПрочитатьДатуJSON, платформа 1С возвращает нам время по стандарту UTC. Если вы запишете эту дату в информационную базу «как есть», пользователи в интерфейсе могут увидеть смещенное время (например, на 3 часа меньше для Московского времени).

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

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


ДатаUTC = ПреобразоватьUnixMillisВДату1С(1554091557065);
ЛокальнаяДатаСервера = МестноеВремя(ДатаUTC); // Смещение произойдет автоматически на основе настроек ОС сервера

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

← На главную