При импорте данных из внешних источников (например, при чтении текстовых файлов, загрузке таблиц Excel или интеграции со сторонними API) разработчики в 1С часто сталкиваются с необходимостью преобразования строкового представления даты в полноценный тип Дата. Ситуация осложняется тем, что даты могут приходить в самых разных форматах: от привычного нам "ДД.ММ.ГГГГ" до международного стандарта ISO или даже в виде неструктурированного текста с названиями месяцев.
В этой статье мы подробно разберем, почему стандартные механизмы преобразования типов могут вызывать ошибки, и рассмотрим наиболее эффективные, безопасные и современные способы решения этой задачи.
Выясним причину, почему простая конструкция вида Дата("23.07.2018") часто приводит к критическому сбою программы. Согласно официальной документации 1С:Предприятия, конструктор Дата() при передаче в него строки ожидает строго определенный формат. Каноническим и самым надежным является формат "ГГГГММДДччммсс" (например, "20180723000000").
Если мы передаем строку в локальном формате (например, с точками-разделителями), поведение системы становится непредсказуемым. Оно начинает напрямую зависеть от локальных настроек операционной системы компьютера (или сервера приложений, если код выполняется на сервере). На одном компьютере с русской локализацией Windows вызов Дата("23.07.2018 00:00:00") может отработать корректно, а на сервере под управлением Linux с англоязычной локалью этот же код неминуемо вызовет аварийное завершение транзакции.
Чтобы гарантировать стабильность кода в любых условиях, необходимо преобразовывать строки к каноническому виду либо явно разбирать их на числовые составляющие.
Рассмотрим ситуацию, когда формат входной строки нам заранее известен — это классическая дата вида "ДД.ММ.ГГГГ" (например, "23.07.2018"). Самым простым и быстрым решением будет выделение подстрок дня, месяца и года с последующим сбором их в каноническую строку или передачей чисел в конструктор.
Посмотрим на пример с использованием функций Сред, Лев и Прав:
ДатаСтрокой = "23.07.2018";
// Извлекаем составляющие части
День = Лев(ДатаСтрокой, 2);
Месяц = Сред(ДатаСтрокой, 4, 2);
Год = Сред(ДатаСтрокой, 7, 4);
// Преобразуем к каноническому виду ГГГГММДД
КаноническаяСтрока = Год + Месяц + День;
МояДата = Дата(КаноническаяСтрока);
Если разделителем в строке может выступать не только точка, но и другие символы, или длина частей может незначительно меняться, надежнее использовать функцию СтрРазделить. Разберем по шагам этот алгоритм:
Функция ПолучитьДатуИзСтроки(СтрокаДаты) Экспорт
// Разбиваем строку по точкам в массив
МассивДаты = СтрРазделить(СтрокаДаты, ".");
// Проверяем, что получили ровно 3 элемента (День, Месяц, Год)
Если МассивДаты.Количество() = 3 Тогда
Год = СокрЛП(МассивДаты[2]);
Месяц = СокрЛП(МассивДаты[1]);
День = СокрЛП(МассивДаты[0]);
// Для надежности дополняем день и месяц ведущими нулями
Если СтрДлина(Месяц) = 1 Тогда Месяц = "0" + Месяц; КонецЕсли;
Если СтрДлина(День) = 1 Тогда День = "0" + День; КонецЕсли;
Возврат Дата(Год + Месяц + День);
КонецЕсли;
Возврат '00010101000000'; // Возвращаем пустую дату, если формат некорректен
КонецФункции
Если в вашей конфигурации используется Библиотека Стандартных Подсистем (БСП), то изобретать собственные велосипеды не нужно. В составе БСП есть замечательный общий модуль СтроковыеФункцииКлиентСервер, в котором реализована готовая функция преобразования строк произвольного вида.
Проанализируем пример ее вызова:
СтрокаДаты = "23.07.2018";
Результат = СтроковыеФункцииКлиентСервер.СтрокаВДату(СтрокаДаты);
// На выходе получаем корректный тип Дата
Эта функция хороша тем, что она самостоятельно очищает строку от лишних пробелов, обрабатывает различные типы разделителей (точки, тире, слэши) и корректно работает со временем, если оно присутствует в строке.
Одной из главных проблем прямого вызова конструктора Дата() является необходимость оборачивать его в конструкцию Попытка...Исключение, чтобы избежать падения программы при передаче мусорных данных. Но есть более изящное и системное решение — использование объекта ОписаниеТипов.
Метод ПривестиЗначение объекта ОписаниеТипов работает безопасно: если строку невозможно преобразовать в дату, он не вызывает исключения, а просто возвращает пустую дату ('00010101000000'). Рассмотрим, как это выглядит в коде:
ОписаниеДаты = Новый ОписаниеТипов("Дата");
// Пример 1: Корректная каноническая строка
МояДата1 = ОписаниеДаты.ПривестиЗначение("20180723");
// Вернет: 23.07.2018 00:00:00
// Пример 2: Некорректные данные
МояДата2 = ОписаниеДаты.ПривестиЗначение("Привет, мир!");
// Вернет пустую дату: 01.01.0001 00:00:00 без вызова ошибок!
В современных версиях платформы 1С:Предприятие реализованы мощные механизмы сериализации данных, которые можно использовать как быстрые "лайфхаки" для парсинга строковых дат международных стандартов (например, формата ISO 8601 вида "ГГГГ-ММ-ДД").
Преобразование через XMLЗначение
Если строка получена из внешней системы в формате "ГГГГ-ММ-ДД", мы можем мгновенно преобразовать ее в дату с помощью глобальной функции XMLЗначение:
СтрокаISO = "2025-01-03";
МояДата = XMLЗначение(Тип("Дата"), СтрокаISO);
// Вернет полноценную дату 1С: 03.01.2025 00:00:00
Преобразование через JSON
Начиная с версии платформы 8.3.6, в 1С доступен метод ПрочитатьДатуJSON. Он незаменим, когда мы работаем с веб-сервисами и API:
// Чтение даты в формате ISO
ДатаISO = ПрочитатьДатуJSON("2025-01-03T15:30:00Z", ФорматДатыJSON.ISO);
// Чтение даты в формате Microsoft ASP.NET
ДатаMS = ПрочитатьДатуJSON("/Date(1710000000000)/", ФорматДатыJSON.Microsoft);
Что делать, если дата находится внутри сложного текстового блока, например, в назначении платежа или в комментариях пользователя ("Оплата по договору от 23.07.2018 за услуги...")? В таких случаях на помощь приходят регулярные выражения.
Начиная с версии платформы 8.3.23, регулярные выражения поддерживаются в 1С нативно. Мы можем легко вычленить дату из текста:
ТекстКомментария = "Заказ был согласован клиентом 23.07.2018 на встрече.";
ШаблонДаты = "\d{2}\.\d{2}\.\d{4}"; // Соответствует формату ДД.ММ.ГГГГ
// Ищем вхождение регулярного выражения
РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ТекстКомментария, ШаблонДаты);
Если РезультатПоиска > 0 Тогда
СтрокаДаты = Сред(ТекстКомментария, РезультатПоиска, 10);
// Теперь передаем выделенную строку в нашу функцию парсинга
МояДата = ПолучитьДатуИзСтроки(СтрокаДаты);
КонецЕсли;
Если ваша база работает на более старых версиях платформы под управлением операционной системы Windows, для регулярных выражений можно использовать COM-объект:
РегВыражение = Новый COMОбъект("VBScript.RegExp");
РегВыражение.Pattern = "\d{2}\.\d{2}\.\d{4}";
РегВыражение.IgnoreCase = Истина;
Если РегВыражение.Test(ТекстКомментария) Тогда
Matches = РегВыражение.Execute(ТекстКомментария);
СтрокаДаты = Matches.Item(0).Value;
МояДата = ПолучитьДатуИзСтроки(СтрокаДаты);
КонецЕсли;
Мы рассмотрели целый арсенал средств для работы со строковыми датами в 1С. Подведем итог и определимся, какой метод в какой ситуации предпочтительнее использовать:
СтрРазделить или функции извлечения подстрок (Сред, Лев). Это быстро и не зависит от внешних библиотек.СтроковыеФункцииКлиентСервер.СтрокаВДату() из состава БСП — она надежна и протестирована тысячами внедрений.ОписаниеТипов вместо классической попытки-исключения. Это ускоряет работу кода и делает его чище.XMLЗначение и ПрочитатьДатуJSON.