Ошибка «Представление даты имеет неверный формат» в ПрочитатьДатуJSON: причины и решение

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

При работе с интеграциями, 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: Правильное удаление символов (через код символа)

Если вы уже получили строку с разделителями и вам нужно её "почистить", необходимо удалять именно неразрывный пробел. В 1С для этого символа существует системное определение — Символы.НПП (Неразрывный Пробел). Исправим код, используя правильную замену:


// Вариант с использованием системной константы (рекомендуется)
ЧистаяСтрока = СтрЗаменить(СтрокаРезультата.Значение, Символы.НПП, "");

// Вариант с указанием кода символа (если версия платформы старая или для понимания сути)
ЧистаяСтрока = СтрЗаменить(СтрокаРезультата.Значение, Символ(160), "");

// Теперь формируем строку для парсинга
СтрокаДляПарсинга = "new Date(" + ЧистаяСтрока + ")";
Результат = ПрочитатьДатуJSON(СтрокаДляПарсинга, ФорматДатыJSON.JavaScript);

Этот метод работает, но он борется с последствиями, а не с причиной.

Решение 2: Форматирование без группировки (Рекомендуемое)

Более правильный подход — изначально не допускать появления разделителей при преобразовании числа в строку. Для этого следует использовать функцию Формат с форматной строкой, отключающей группировку (параметр ЧГ=0). Рассмотрим пример правильной реализации:


// Предположим, СтрокаРезультата.Значение - это Число 1439769600000
СтрокаЧислом = Формат(СтрокаРезультата.Значение, "ЧГ=0"); // Результат: "1439769600000"

// Формируем конструкцию для JavaScript формата
СтрокаJSON = "new Date(" + СтрокаЧислом + ")";

Попытка
    Дата1С = ПрочитатьДатуJSON(СтрокаJSON, ФорматДатыJSON.JavaScript);
Исключение
    // Обработка ошибки, если формат все же неверный
    Сообщить("Ошибка чтения даты: " + ОписаниеОшибки());
КонецПопытки;

Использование ЧГ=0 гарантирует, что в строке будут только цифры, независимо от региональных настроек информационной базы или операционной системы.

Решение 3: Использование объекта ЧтениеJSON

Если данные приходят к вам в виде полноценного 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:

  1. Проверьте, не содержит ли строка с числом пробелов. В 1С при преобразовании чисел они появляются автоматически как неразрывные пробелы (код 160).
  2. Используйте Формат(Значение, "ЧГ=0") для преобразования чисел в строки без разделителей.
  3. Если вы удаляете пробелы через СтрЗаменить, используйте Символы.НПП, а не просто строку " ".
  4. Рассмотрите возможность отказа от ПрочитатьДатуJSON в пользу математического вычисления даты от 1970 года, если на входе у вас просто число (timestamp).

Понимание механизма форматирования чисел в платформе поможет избежать множества подобных ошибок в будущем при формировании строковых запросов и JSON-структур.

← На главную