При интеграции 1С с внешними системами через JSON-сервисы часто возникает ситуация, когда временные метки передаются в формате Unix Timestamp (количество секунд, прошедших с 1 января 1970 года). Однако иногда эти данные приходят в виде строки с научной нотацией, например, "1.5383412E9". Попытка просто использовать функцию Число() в 1С для такой строки приведет к ошибке, так как платформа не умеет напрямую преобразовывать символ экспоненты «E» в число.
В этой статье мы подробно разберем, как правильно интерпретировать такие данные, преобразовывать их в числовой формат и получать корректную дату в 1С, учитывая часовые пояса и возможные погрешности.
Для начала проанализируем, что скрывается за строкой 1.5383412E9. Это стандартная математическая запись, где число после буквы «E» означает степень десятки, на которую нужно умножить число, стоящее перед буквой. В нашем случае:
1.5383412 * 10^9 = 1 538 341 200 секунд.
Поскольку это Unix Timestamp (UT), отсчет ведется от «начала эпохи» — 01.01.1970 00:00:00 UTC. Наша задача в 1С сводится к трем этапам: получение числа из строки, добавление полученных секунд к базовой дате и корректировка по часовому поясу.
Если функция Число() не справляется, мы можем самостоятельно разобрать строку. Разберем ситуацию по шагам: найдем позицию символа «E», выделим мантиссу (число до E) и порядок (степень после E).
Рассмотрим пример программного кода для реализации этого алгоритма:
Функция ПреобразоватьЭкспонентуВЧисло(Знач ВходнаяСтрока) Экспорт
ВходнаяСтрока = Врег(СокрЛП(ВходнаяСтрока));
ПозицияЕ = СтрНайти(ВходнаяСтрока, "E");
Если ПозицияЕ = 0 Тогда
Возврат Число(ВходнаяСтрока); // Если "E" нет, это обычное число
КонецЕсли;
МантиссаСтрокой = Лев(ВходнаяСтрока, ПозицияЕ - 1);
ПорядокСтрокой = Сред(ВходнаяСтрока, ПозицияЕ + 1);
// Заменяем точку на десятичный разделитель, установленный в системе
МантиссаСтрокой = СтрЗаменить(МантиссаСтрокой, ".", "");
МантиссаСтрокой = СтрЗаменить(МантиссаСтрокой, ",", "");
// Для надежности лучше использовать программное определение разделителя,
// но здесь мы просто преобразуем мантиссу к числу через XML
Мантисса = XMLЗначение(Тип("Число"), СтрЗаменить(Лев(ВходнаяСтрока, ПозицияЕ - 1), ",", "."));
Порядок = Число(ПорядокСтрокой);
Возврат Мантисса * Pow(10, Порядок);
КонецФункции
В данном примере функция Pow(10, Порядок) возводит 10 в нужную степень, что позволяет нам вычислить точное количество секунд даже для очень больших чисел.
Существует более лаконичный способ, который часто упускают из виду. Платформа 1С поддерживает стандарты XML, где научная нотация (Scientific Notation) для типов double и decimal является стандартной. Функция XMLЗначение часто понимает букву «E» корректно, если строка соответствует формату.
Проанализируем пример использования:
СтрокаJSON = "1.5383412E9";
// Важно: XMLЗначение ожидает точку в качестве разделителя
ЧислоСекунд = XMLЗначение(Тип("Число"), СтрЗаменить(СтрокаJSON, ",", "."));
РезультатДата = Дата(1970, 1, 1) + ЧислоСекунд;
Важный нюанс: Результат будет соответствовать времени по Гринвичу (UTC). Если ваш сервер 1С находится в Москве (UTC+3), то дата будет отличаться от локальной на 3 часа.
Выясним, как сделать полученную дату «человеческой» для пользователя. В 1С тип Дата не содержит сведений о поясе, поэтому мы должны добавить смещение вручную или использовать системные функции.
Разберем полный цикл преобразования с учетом часового пояса (на примере UTC+3):
СтрокаЭкспонента = "1.5383412E9";
КоличествоСекунд = XMLЗначение(Тип("Число"), СтрЗаменить(СтрокаЭкспонента, ",", "."));
БазоваяДата = Дата(1970, 1, 1);
ДатаUTC = БазоваяДата + КоличествоСекунд;
// Смещение в секундах (например, для МСК +3 часа: 3 * 3600 = 10800)
СмещениеПояса = 10800;
ЛокальнаяДата = ДатаUTC + СмещениеПояса;
Сообщить("Дата по UTC: " + ДатаUTC);
Сообщить("Локальная дата: " + ЛокальнаяДата);
Если мы используем платформу 8.3.15 и выше, можно применить функцию МестноеВремя(), чтобы избежать жесткого прописывания констант в коде:
// Предположим, сервер работает в нужном нам часовом поясе
ЛокальнаяДата = МестноеВремя(ДатаUTC, ЧасовойПоясСеанса());
Проанализируем ситуацию: почему число вообще пришло в виде строки с «E»? Часто это происходит при использовании ЧтениеJSON, если число в самом файле JSON было записано слишком длинным или если сторонний сервис передает его в кавычках как строку.
Если вы используете встроенную функцию ПрочитатьJSON(), старайтесь использовать функцию восстановления (параметр ФункцияВосстановления). Это позволит вам преобразовать Unix Timestamp в полноценную дату 1С прямо в момент десериализации объекта.
Посмотрим на пример функции-обработчика:
Функция ОбработкаJSON(Свойство, Значение, ДополнительныеПараметры) Экспорт
Если Свойство = "timestamp" Тогда
// Проверяем, не является ли значение научной нотацией
ЧислоЗначение = XMLЗначение(Тип("Число"), СтрЗаменить(Строка(Значение), ",", "."));
Возврат Дата(1970, 1, 1) + ЧислоЗначение;
КонецЕсли;
Возврат Значение;
КонецФункции
При работе с данными из веб-сервисов (особенно на базе Node.js или Java) следует помнить, что Unix Time может передаваться не в секундах, а в миллисекундах. В этом случае число в экспоненциальной форме будет выглядеть примерно так: "1.5383412E12".
Выясним причину ошибки: если прибавить такое число к дате, вы получите дату далеко в будущем (через тысячи лет). Поэтому, если после преобразования «E» вы видите число из 13 и более знаков, обязательно делите его на 1000 перед сложением с датой 1970 года.
Резюмируем последовательность действий:
XMLЗначение или ручной парсинг).Дата(1970, 1, 1).Используя эти методы, вы сможете корректно обрабатывать любые форматы временных меток, которые возвращают современные API, обеспечивая точность и удобство работы пользователей в вашей конфигурации 1С.