В практике разработчика 1С часто возникает задача импорта данных из внешних источников: Excel-файлов, текстовых выписок или веб-сервисов. Одной из самых коварных проблем является получение даты в «человеческом» формате, например, «4 сентября 2024 г.». Поскольку встроенная функция Дата() ожидает строго определенный формат (ГГГГММДДЧЧММСС), нам необходимо разобрать строку на составляющие и преобразовать их в понятный системе вид. В этой статье мы подробно рассмотрим несколько способов решения этой задачи, начиная от классических алгоритмов и заканчивая современными возможностями платформы 8.3.23.
Если ваша конфигурация построена на базе БСП (а это почти все современные решения: БП 3.0, ERP, ЗУП 3.1), первым делом стоит обратиться к стандартным модулям. Проанализируем возможности функции СтрокаВДату. Основная сложность заключается в том, что стандартная функция не всегда понимает названия месяцев в родительном падеже.
Рассмотрим алгоритм действий при использовании БСП:
СтроковыеФункцииКлиентСервер.СтрокаВДату().Пример реализации через замену месяца может выглядеть так:
Функция ПреобразоватьТекстВДату(Знач ТекстДаты)
ТекстДаты = НРег(ТекстДаты); // Приводим к нижнему регистру
ТекстДаты = СтрЗаменить(ТекстДаты, " г.", "");
// Массив месяцев в родительном падеже
Месяцы = "января,февраля,марта,апреля,мая,июня,июля,августа,сентября,октября,ноября,декабря";
МассивМесяцев = СтрРазделить(Месяцы, ",");
Для НомерМесяца = 1 По 12 Цикл
ИмяМесяца = МассивМесяцев[НомерМесяца - 1];
Если СтрНайти(ТекстДаты, ИмяМесяца) > 0 Тогда
// Заменяем название месяца на число с ведущим нулем
ТекстДаты = СтрЗаменить(ТекстДаты, ИмяМесяца, Формат(НомерМесяца, "ЧЦ=2; ЧГ=0"));
Прервать;
КонецЕсли;
КонецЦикла;
Возврат СтроковыеФункцииКлиентСервер.СтрокаВДату(ТекстДаты);
КонецФункции
Начиная с версии платформы 8.3.23, разработчикам стали доступны встроенные регулярные выражения. Это революционное изменение позволяет отказаться от сложных циклов и многократных вызовов СтрЗаменить. Проанализируем ситуацию: нам нужно извлечь число (день), текст (месяц) и число (год).
Разберем по шагам, как применить новый функционал:
СтрНайти() с параметром регулярного выражения для поиска групп цифр и букв.День, МесяцТекст и Год.Соответствие или поиск в эталонной строке.Преимущество этого метода в том, что регулярное выражение (\d+)\s+([а-яА-Я]+)\s+(\d+) легко справится с любым количеством пробелов между словами, что часто встречается в некачественных входных данных.
Если нам необходимо решение, работающее на старых версиях платформы или без использования БСП, мы можем реализовать парсинг самостоятельно. Разберем наиболее надежный алгоритм сборки даты через конструктор Дата(Год, Месяц, День).
Посмотрим на пример кода, который учитывает особенности склонения месяцев и очистку строки:
Функция ДатаИзСтроки(Знач ИсходнаяСтрока) Экспорт
// 1. Очистка строки
СтрокаОбработки = СокрЛП(НРег(ИсходнаяСтрока));
СтрокаОбработки = СтрЗаменить(СтрокаОбработки, " г.", "");
// 2. Разбиение на части по пробелу
ЧастиДаты = СтрРазделить(СтрокаОбработки, " ", Ложь);
Если ЧастиДаты.Количество() < 3 Тогда
Возврат '00010101'; // Некорректный формат
КонецЕсли;
ЧислоД = Число(ЧастиДаты[0]);
ТекстМ = ЧастиДаты[1];
ЧислоГ = Число(ЧастиДаты[2]);
// 3. Определение номера месяца
СписокМесяцев = "янв,фев,мар,апр,май,июн,июл,авг,сен,окт,ноя,дек";
МассивСокращений = СтрРазделить(СписокМесяцев, ",");
ЧислоМ = 0;
Для Индекс = 0 По 11 Цикл
Если СтрНайти(ТекстМ, МассивСокращений[Индекс]) = 1 Тогда
ЧислоМ = Индекс + 1;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЧислоМ = 0 Тогда
Возврат '00010101';
КонецЕсли;
// 4. Сборка объекта Дата
Попытка
Возврат Дата(ЧислоГ, ЧислоМ, ЧислоД);
Исключение
Возврат '00010101';
КонецПопытки;
КонецФункции
При реализации любого из подходов важно учитывать несколько критических моментов, с которыми мы можем столкнуться в промышленной эксплуатации:
НРег(). Для системы «Сентября» и «сентября» — это разные строки.Дата(Год, Месяц, День) принимает числовые значения, поэтому наличие или отсутствие ведущего нуля (например, «04» или «4») для него не имеет значения. А вот если вы собираете дату строкой «ГГГГММДД», обязательно используйте Формат(Значение, "ЧЦ=2; ЧГ=0") для дополнения нулями.СтрНайти с регулярными выражениями потребует от вас отключения режима совместимости (минимум до 8.3.23). Если ваша конфигурация работает в режиме совместимости 8.3.10 или 8.3.20, вам придется использовать классические методы обработки строк.Проанализировав вышеописанные способы, можно сделать вывод: наиболее надежным и современным является метод с использованием регулярных выражений, но для широкой совместимости лучше использовать классический разбор через СтрРазделить и поиск месяца по сокращенному названию.