Как преобразовать строку с названием месяца «4 сентября 2024 г.» в формат Даты 1С

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

В практике разработчика 1С часто возникает задача импорта данных из внешних источников: Excel-файлов, текстовых выписок или веб-сервисов. Одной из самых коварных проблем является получение даты в «человеческом» формате, например, «4 сентября 2024 г.». Поскольку встроенная функция Дата() ожидает строго определенный формат (ГГГГММДДЧЧММСС), нам необходимо разобрать строку на составляющие и преобразовать их в понятный системе вид. В этой статье мы подробно рассмотрим несколько способов решения этой задачи, начиная от классических алгоритмов и заканчивая современными возможностями платформы 8.3.23.

Метод 1: Использование Библиотеки стандартных подсистем (БСП)

Если ваша конфигурация построена на базе БСП (а это почти все современные решения: БП 3.0, ERP, ЗУП 3.1), первым делом стоит обратиться к стандартным модулям. Проанализируем возможности функции СтрокаВДату. Основная сложность заключается в том, что стандартная функция не всегда понимает названия месяцев в родительном падеже.

Рассмотрим алгоритм действий при использовании БСП:

  1. Предварительно подготовим строку, удалив лишние символы, такие как «г.» или лишние пробелы.
  2. Заменим текстовое название месяца на его порядковый номер.
  3. Передадим полученную строку в функцию СтроковыеФункцииКлиентСервер.СтрокаВДату().

Пример реализации через замену месяца может выглядеть так:


Функция ПреобразоватьТекстВДату(Знач ТекстДаты)
    
    ТекстДаты = НРег(ТекстДаты); // Приводим к нижнему регистру
    ТекстДаты = СтрЗаменить(ТекстДаты, " г.", "");
    
    // Массив месяцев в родительном падеже
    Месяцы = "января,февраля,марта,апреля,мая,июня,июля,августа,сентября,октября,ноября,декабря";
    МассивМесяцев = СтрРазделить(Месяцы, ",");
    
    Для НомерМесяца = 1 По 12 Цикл
        ИмяМесяца = МассивМесяцев[НомерМесяца - 1];
        Если СтрНайти(ТекстДаты, ИмяМесяца) > 0 Тогда
            // Заменяем название месяца на число с ведущим нулем
            ТекстДаты = СтрЗаменить(ТекстДаты, ИмяМесяца, Формат(НомерМесяца, "ЧЦ=2; ЧГ=0"));
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Возврат СтроковыеФункцииКлиентСервер.СтрокаВДату(ТекстДаты);
    
КонецФункции

Метод 2: Регулярные выражения в платформе 8.3.23 и выше

Начиная с версии платформы 8.3.23, разработчикам стали доступны встроенные регулярные выражения. Это революционное изменение позволяет отказаться от сложных циклов и многократных вызовов СтрЗаменить. Проанализируем ситуацию: нам нужно извлечь число (день), текст (месяц) и число (год).

Разберем по шагам, как применить новый функционал:

  1. Используем метод СтрНайти() с параметром регулярного выражения для поиска групп цифр и букв.
  2. Полученные части строки помещаем в переменные День, МесяцТекст и Год.
  3. Преобразуем текстовый месяц в число через Соответствие или поиск в эталонной строке.

Преимущество этого метода в том, что регулярное выражение (\d+)\s+([а-яА-Я]+)\s+(\d+) легко справится с любым количеством пробелов между словами, что часто встречается в некачественных входных данных.

Метод 3: Ручной разбор строки (Универсальный подход)

Если нам необходимо решение, работающее на старых версиях платформы или без использования БСП, мы можем реализовать парсинг самостоятельно. Разберем наиболее надежный алгоритм сборки даты через конструктор Дата(Год, Месяц, День).

Посмотрим на пример кода, который учитывает особенности склонения месяцев и очистку строки:


Функция ДатаИзСтроки(Знач ИсходнаяСтрока) Экспорт
    
    // 1. Очистка строки
    СтрокаОбработки = СокрЛП(НРег(ИсходнаяСтрока));
    СтрокаОбработки = СтрЗаменить(СтрокаОбработки, " г.", "");
    
    // 2. Разбиение на части по пробелу
    ЧастиДаты = СтрРазделить(СтрокаОбработки, " ", Ложь);
    
    Если ЧастиДаты.Количество() < 3 Тогда
        Возврат '00010101'; // Некорректный формат
    КонецЕсли;
    
    ЧислоД = Число(ЧастиДаты[0]);
    ТекстМ = ЧастиДаты[1];
    ЧислоГ = Число(ЧастиДаты[2]);
    
    // 3. Определение номера месяца
    СписокМесяцев = "янв,фев,мар,апр,май,июн,июл,авг,сен,окт,ноя,дек";
    МассивСокращений = СтрРазделить(СписокМесяцев, ",");
    
    ЧислоМ = 0;
    Для Индекс = 0 По 11 Цикл
        Если СтрНайти(ТекстМ, МассивСокращений[Индекс]) = 1 Тогда
            ЧислоМ = Индекс + 1;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ЧислоМ = 0 Тогда
        Возврат '00010101';
    КонецЕсли;
    
    // 4. Сборка объекта Дата
    Попытка
        Возврат Дата(ЧислоГ, ЧислоМ, ЧислоД);
    Исключение
        Возврат '00010101';
    КонецПопытки;
    
КонецФункции

Важные нюансы при работе с «естественными» датами

При реализации любого из подходов важно учитывать несколько критических моментов, с которыми мы можем столкнуться в промышленной эксплуатации:

Проанализировав вышеописанные способы, можно сделать вывод: наиболее надежным и современным является метод с использованием регулярных выражений, но для широкой совместимости лучше использовать классический разбор через СтрРазделить и поиск месяца по сокращенному названию.

← На главную