При работе с интеграциями, REST API и обменом данными в формате JSON мы часто сталкиваемся с необходимостью парсинга дат. Одной из распространенных задач является преобразование даты из формата Unix Timestamp (количество миллисекунд с 1 января 1970 года) в дату 1С. Однако использование метода ПрочитатьДатуJSON может привести к неожиданным ошибкам, даже если на первый взгляд передаваемые данные кажутся корректными.
В этой статье мы подробно разберем ситуацию, когда платформа выдает ошибку "Представление даты имеет неверный формат", выясним, откуда берутся "невидимые" символы, ломающие код, и рассмотрим несколько способов корректного решения этой задачи.
Рассмотрим ситуацию, с которой столкнулся разработчик. Задача состоит в том, чтобы преобразовать числовое значение (Timestamp), полученное от сервера (например, 1439769600000), в дату 1С, используя формат JavaScript.
Код, вызывающий ошибку, выглядит следующим образом:
// СтрокаРезультата.Значение содержит число или строку с числом 1 439 769 600 000
СтрокаДатаФормат = ПрочитатьДатуJSON(
"new Date(" + Формат(СтрокаРезультата.Значение, "ЧГ=") + ")",
ФорматДатыJSON.JavaScript
);
При выполнении этого кода система выдает ошибку:
Представление даты имеет неверный формат ('new Date(1 439 769 600 000)')
На первый взгляд может показаться, что проблема в синтаксисе обертки new Date(), но если присмотреться к тексту ошибки, можно заметить пробелы внутри числа: 1 439 769 600 000. Именно эти разделители и являются корнем проблемы.
Давайте разберемся, как 1С преобразует числа в строки. Если мы берем числовое значение (например, полученное из JSON как число или хранящееся в переменной типа Число) и неявно или явно преобразуем его в строку (функцией Строка() или конкатенацией), платформа применяет настройки регионального формата представления чисел.
По умолчанию в русской локализации 1С для чисел используется группировка разрядов (по три цифры). Разделителем групп выступает не обычный пробел (код ASCII 32), а неразрывный пробел (NBSP, код ASCII 160).
Когда мы пытаемся удалить пробелы стандартным способом:
// Попытка удалить обычный пробел
ЧистаяСтрока = СтрЗаменить(Строка(СтрокаРезультата.Значение), " ", "");
Это не срабатывает, так как функция СтрЗаменить ищет символ с кодом 32, а в строке находится символ с кодом 160. В результате строка остается прежней: "1 439 769 600 000".
Метод ПрочитатьДатуJSON (и внутренний парсер JSON) ожидает строгого соответствия формату. В JavaScript число не может содержать пробелов. Выражение new Date(1 439...) является синтаксически ошибочным для JS, и парсер 1С справедливо сообщает о неверном формате.
Если вы уже получили строку с разделителями и вам нужно её "почистить", необходимо удалять именно неразрывный пробел. В 1С для этого символа существует системное определение — Символы.НПП (Неразрывный Пробел).
Исправим код, используя правильную замену:
// Вариант с использованием системной константы (рекомендуется)
ЧистаяСтрока = СтрЗаменить(СтрокаРезультата.Значение, Символы.НПП, "");
// Вариант с указанием кода символа (если версия платформы старая или для понимания сути)
ЧистаяСтрока = СтрЗаменить(СтрокаРезультата.Значение, Символ(160), "");
// Теперь формируем строку для парсинга
СтрокаДляПарсинга = "new Date(" + ЧистаяСтрока + ")";
Результат = ПрочитатьДатуJSON(СтрокаДляПарсинга, ФорматДатыJSON.JavaScript);
Этот метод работает, но он борется с последствиями, а не с причиной.
Более правильный подход — изначально не допускать появления разделителей при преобразовании числа в строку. Для этого следует использовать функцию Формат с форматной строкой, отключающей группировку (параметр ЧГ=0).
Рассмотрим пример правильной реализации:
// Предположим, СтрокаРезультата.Значение - это Число 1439769600000
СтрокаЧислом = Формат(СтрокаРезультата.Значение, "ЧГ=0"); // Результат: "1439769600000"
// Формируем конструкцию для JavaScript формата
СтрокаJSON = "new Date(" + СтрокаЧислом + ")";
Попытка
Дата1С = ПрочитатьДатуJSON(СтрокаJSON, ФорматДатыJSON.JavaScript);
Исключение
// Обработка ошибки, если формат все же неверный
Сообщить("Ошибка чтения даты: " + ОписаниеОшибки());
КонецПопытки;
Использование ЧГ=0 гарантирует, что в строке будут только цифры, независимо от региональных настроек информационной базы или операционной системы.
Если данные приходят к вам в виде полноценного JSON-ответа, часто не имеет смысла вырезать отдельные куски и парсить их вручную через ПрочитатьДатуJSON. Лучше использовать штатный механизм чтения JSON, который умеет восстанавливать даты автоматически, если указать соответствующие параметры.
Рассмотрим пример чтения всего объекта:
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ВходящаяСтрокаJSON);
// Указываем имена свойств, которые нужно попытаться преобразовать в даты
МассивИменСвойств = Новый Массив;
МассивИменСвойств.Добавить("dateField"); // Имя поля в JSON
// Читаем JSON, указывая формат даты (обычно ISO или JavaScript)
Данные = ПрочитатьJSON(Чтение, , МассивИменСвойств, ФорматДатыJSON.ISO);
// Примечание: для числовых timestamp автоматическое преобразование может работать специфично,
// поэтому часто надежнее получать число и преобразовывать его математически.
Однако, стоит отметить, что автоматическое преобразование ПрочитатьJSON для числовых Timestamp (формат JavaScript) работает лучше всего, когда дата в JSON передана именно как строка "new Date(...)". Если же там просто число, 1С прочитает его как Число.
Самый надежный и быстрый способ преобразовать Unix Timestamp (число миллисекунд) в дату 1С — это простая математика. Этот метод не зависит от парсеров JSON и работает стабильно. Логика проста: Unix Timestamp — это количество секунд (или миллисекунд), прошедших с начала эпохи Unix (01.01.1970 00:00:00 UTC).
// Исходное значение (миллисекунды)
Таймштамп = 1439769600000;
// Начало эпохи Unix
ДатаНачала = Дата(1970, 1, 1);
// Преобразуем миллисекунды в секунды и прибавляем к дате
// Важно: Результат будет в UTC (без учета часового пояса)
ДатаUTC = ДатаНачала + (Таймштамп / 1000);
// Если нужно привести к локальному времени сеанса (если требуется)
// Можно добавить смещение часового пояса, но это зависит от задачи.
// Простой способ для текущего пояса сервера:
ДатаЛокальная = ДатаUTC + (ТекущаяДата() - ТекущаяДатаСеанса()); // Условный пример смещения
Этот метод полностью исключает проблемы с форматами строк, пробелами и кавычками.
Если вы столкнулись с ошибкой при чтении даты JSON:
Формат(Значение, "ЧГ=0") для преобразования чисел в строки без разделителей.СтрЗаменить, используйте Символы.НПП, а не просто строку " ".ПрочитатьДатуJSON в пользу математического вычисления даты от 1970 года, если на входе у вас просто число (timestamp).Понимание механизма форматирования чисел в платформе поможет избежать множества подобных ошибок в будущем при формировании строковых запросов и JSON-структур.