Как преобразовать строку в дату в 1С, если стандартная функция выдает ошибку?

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

Введение в проблему типизации дат

При интеграции 1С с внешними системами (сайты, API сервисов бронирования, мобильные приложения) мы часто сталкиваемся с тем, что данные приходят в текстовом виде. Казалось бы, задача тривиальна: превратить строку "2024-12-15" в объект системы Дата. Однако многие разработчики, особенно начинающие, спотыкаются о строгую типизацию, хотя работа с датами в 1С:Предприятие — это базовый навык, требующий понимания нюансов платформы.

Рассмотрим классическую ошибку, которая возникает при попытке выполнить код вида:


// Ошибка: Преобразование значения к типу Дата не может быть выполнено
ДатаЗаселения = Дата("2024-12-15");

Мы подробно разберем, почему так происходит, какие форматы понимает платформа "из коробки", и, самое главное, изучим надежные способы преобразования строк в даты, включая работу с форматом ISO 8601, JSON и использование Библиотеки Стандартных Подсистем (БСП) — в поиске причин ошибок поможет инструмент пошаговой отладки кода и просмотра значений переменных.

Почему функция Дата() не работает со строкой?

Давайте обратимся к синтаксис-помощнику. Конструктор Дата() в 1С:Предприятии — инструмент мощный, но довольно консервативный. Если мы передаем в него строку, платформа ожидает увидеть данные в одном из двух форматов:

  1. Канонический формат: YYYYMMDDHHMMSS. Это жесткая строка из цифр. Например, "20241215000000". Если в строке есть разделители (тире, точки), этот вариант не сработает.
  2. Локальный формат: Это то, как дата отображается пользователю в вашей операционной системе и настройках 1С. Чаще всего для русскоязычной локали это "ДД.ММ.ГГГГ ЧЧ:мм:сс". Например, "15.12.2024 00:00:00".

В рассматриваемой нами ситуации строка имеет вид "2024-12-15" (или "2024-12-15T14:30:00"). Это международный стандарт ISO 8601, который является стандартом де-факто для обмена данными в вебе (JSON, XML). Но для функции Дата() — это просто набор символов с непонятными дефисами.

Решение 1: Использование XMLЗначение (Самый быстрый способ для ISO)

Если мы точно знаем, что к нам приходит строка в формате ISO (год-месяц-день, разделитель дефис), самым элегантным и нативным способом преобразования является использование механизма XML-сериализации. Платформа 1С прекрасно умеет работать с типами XML Schema, где формат даты строго регламентирован. Если помимо конвертации вам необходимо превратить XML в красивый отчет, можно воспользоваться технологией XSLT.

Рассмотрим код, который решает проблему в одну строку:


СтрокаДаты = "2024-12-15";
// Преобразуем строку ISO в дату 1С
ДатаЗаселения = XMLЗначение(Тип("Дата"), СтрокаДаты);

Этот метод хорош тем, что он понимает как формат date (только дата), так и dateTime (дата и время с разделителем T).


// Работает и с полным форматом времени
СтрокаВремени = "2024-12-15T12:00:00";
ДатаЗаселения = XMLЗначение(Тип("Дата"), СтрокаВремени);

Важный нюанс: Часовые пояса (Timezone)

При использовании XMLЗначение мы должны быть внимательны к букве "Z" в конце строки (например, "2023-12-31T21:00:00Z"). Символ "Z" означает время в формате UTC (нулевой меридиан).

Тип Дата в 1С не хранит информацию о часовом поясе. Когда XMLЗначение видит суффикс "Z" или смещение часового пояса (например, +03:00), функция пытается привести время к локальному времени сеанса (клиента или сервера, где выполняется код).

Это может привести к тому, что дата "съедет" на день назад или вперед. Если вам нужно сохранить "сырое" значение времени без поправок на часовой пояс сервера, может потребоваться предварительная обработка строки (удаление "Z") или использование более сложных механизмов, таких как специализированный инструмент для конвертации данных — для этого подойдёт инструмент для отладки кода и анализа объектов при конвертации данных.

Решение 2: Использование Фабрики XDTO (Строкая типизация)

Если мы хотим писать академически правильный код или работаем со сложными структурами, используем глобальную фабрику XDTO. Этот метод аналогичен предыдущему, но позволяет явно указать, какой именно тип данных мы ожидаем прочитать — только дату или дату со временем.


// Явно указываем, что читаем тип "date" из пространства имен XML Schema
ТипДатаXML = ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema", "date");
СтрокаДаты = "2024-12-15";

// Создаем объект XDTO и получаем его значение
ДатаЗаселения = ФабрикаXDTO.Создать(ТипДатаXML, СтрокаДаты).Значение;

Это защищает нас от ситуаций, когда формат строки неоднозначен.

Решение 3: Функции Библиотеки Стандартных Подсистем (БСП)

В современных типовых конфигурациях (1С:Бухгалтерия, 1С:ERP, 1С:УТ и др.) всегда внедрена Библиотека Стандартных Подсистем. Она содержит готовые функции на все случаи жизни, в том числе и для преобразования дат. Для тех, кто хочет глубже изучить возможности библиотеки, рекомендуем использовать справочник по методам БСП.

Использование методов БСП предпочтительно, так как они умеют "переваривать" разные форматы ввода и часто содержат обработку ошибок. В теме на форуме были упомянуты два модуля. Давайте разберемся, какой использовать.

Модуль СтроковыеФункцииКлиентСервер

Это современный профильный модуль для работы со строками. Рекомендуем использовать именно его.


// Пример использования функции из БСП
// Функция пытается распознать формат автоматически
ДатаЗаселения = СтроковыеФункцииКлиентСервер.СтрокаВДату("2024-12-15");

Функция СтрокаВДату в этом модуле довольно интеллектуальна. Она может принимать второй параметр — описание формата, но часто справляется и без него.

Модуль ОбщегоНазначенияКлиентСервер

В старых версиях конфигураций или в коде, написанном несколько лет назад, можно встретить вызов:


ДатаЗаселения = ОбщегоНазначенияКлиентСервер.СтрокаВДату("2024-12-15");

Сейчас этот метод часто является "оберткой" (wrapper), которая внутри себя вызывает методы из СтроковыеФункцииКлиентСервер. Для нового кода лучше сразу обращаться к специализированному модулю строковых функций, чтобы избежать использования устаревающих методов.

Решение 4: Правильное чтение JSON (Превентивный удар)

Проанализируем контекст задачи. Переменная автора называлась Гость.arrives. Скорее всего, это поле из JSON-ответа от API отеля или сайта. Если вы занимаетесь быстрой организацией HTTP-сервиса, правильная обработка типов данных на входе сэкономит массу времени.

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


ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);

// Указываем платформе, что даты в JSON идут в формате ISO
ПараметрыЧтения = Новый ПараметрыЧтенияJSON( , ОжидаемыйФорматДатыJSON.ISO);

Данные = ПрочитатьJSON(ЧтениеJSON, ПараметрыЧтения);

// Теперь Данные.arrives — это уже тип "Дата", а не "Строка"!
ДатаЗаселения = Данные.arrives; 

Это самый профессиональный подход при работе с JSON.

Решение 5: Microsoft JSON Date Format

Иногда, работая с Legacy-системами на базе .NET, вы можете получить дату в таком странном виде: "/Date(1702638000000)/".

Здесь ни XMLЗначение, ни стандартные функции не помогут. Число внутри скобок — это количество миллисекунд, прошедших с "Эпохи Unix" (1 января 1970 года). Разберем алгоритм преобразования такой строки:


СтрокаМС = "/Date(1702638000000)/";

// 1. Очищаем строку от лишнего мусора, оставляем только цифры
// (В реальности лучше использовать RegExp или СтрНайти/Сред для надежности)
ЧислоСтр = Сред(СтрокаМС, 7, СтрДлина(СтрокаМС) - 8); 

// 2. Преобразуем в число
Миллисекунды = Число(ЧислоСтр);

// 3. Добавляем секунды к базовой дате (делим мс на 1000)
ДатаЗаселения = Дата(1970, 1, 1) + (Миллисекунды / 1000);

Решение 6: RegExp для нестандартных форматов

Если вы получаете дату в "человеческом" формате, например, "Dec 15, 2024" или "12/15/2024" (американский формат), стандартные средства 1С бессильны — здесь поможет обработка валидации и исправления дат при помощи ИИ.

В этом случае нам придется парсить строку самостоятельно. На операционных системах Windows удобно использовать COM-объект VBScript.RegExp.

Рассмотрим пример для формата "MM/DD/YYYY":


ВходящаяСтрока = "12/15/2024";

RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.Pattern = "(\d{2})/(\d{2})/(\d{4})"; // Ищем группы цифр

Если RegExp.Test(ВходящаяСтрока) Тогда
    Matches = RegExp.Execute(ВходящаяСтрока);
    SubMatches = Matches.Item(0).SubMatches;
    
    Месяц = Число(SubMatches.Item(0));
    День  = Число(SubMatches.Item(1));
    Год   = Число(SubMatches.Item(2));
    
    ДатаЗаселения = Дата(Год, Месяц, День);
КонецЕсли;

На серверах под управлением Linux использование COM-объектов невозможно. Там придется использовать строковые функции встроенного языка: СтрРазделить, СтрНайти, Лев, Прав, Сред для извлечения частей даты.

Заключение

Подведем итоги. Ошибка преобразования строки в дату возникает из-за несовпадения форматов. Чтобы решить задачу грамотно:

  1. Проверьте, можно ли настроить чтение даты на уровне ПрочитатьJSON.
  2. Если строка в формате ISO (YYYY-MM-DD) — используйте XMLЗначение(Тип("Дата"), Стр).
  3. Если вы работаете в типовой конфигурации — используйте СтроковыеФункцииКлиентСервер.СтрокаВДату().
  4. В нестандартных случаях — пишите свой парсер через строковые функции или регулярные выражения.
← На главную