Как преобразовать строку в дату в 1С: разбираем все способы и исправляем ошибки

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

В процессе разработки в среде «1С:Предприятие» нам регулярно приходится сталкиваться с необходимостью импорта или ручного разбора текстовых данных. Одной из самых частых задач в этой сфере является преобразование строкового представления даты в полноценный тип данных Дата. Ситуация усложняется, когда исходная строка представлена в сокращенном формате, например, «28.06.86», где год указан всего двумя цифрами, а разделители или длина составляющих частей могут варьироваться.

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

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

Начнем с классической ошибки, которую часто совершают начинающие разработчики. Попытка использовать конструкцию вида Формат("28.06.86", "ДФ=dd.MM.yyyy") для получения даты из строки гарантированно завершится неудачей.

Давайте проанализируем назначение этой функции. Функция Формат() предназначена исключительно для преобразования «изнутри наружу». Она принимает на вход готовое системное значение (например, число, булево или дату) и возвращает красивую, удобочитаемую строку в соответствии с переданной маской форматирования. Преобразовывать строку обратно в объект даты эта функция физически не умеет. Нам придется задействовать другие платформенные механизмы.

Способ №1: Использование функции СтрРазделить() и обработка двузначного года

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

Рассмотрим по шагам, как реализовать этот алгоритм с проверкой «века» для двузначного года:


ДатаСтрокой = "28.06.86";
МассивЧастиДаты = СтрРазделить(ДатаСтрокой, ".", Истина);

Если МассивЧастиДаты.Количество() = 3 Тогда
    День  = МассивЧастиДаты[0];
    Месяц = МассивЧастиДаты[1];
    Год   = МассивЧастиДаты[2];
    
    // Приводим год к четырехзначному формату
    Если СтрДлина(Год) = 2 Тогда
        // Задаем границу веков. Например, всё, что больше "30" — это 20-й век (19хх), остальное — 21-й (20хх)
        Год = ?(Год > "30", "19" + Год, "20" + Год);
    КонецЕсли;
    
    // Собираем каноническую строку вида ГГГГММДД
    КаноническаяСтрока = Год + Месяц + День;
    
    Попытка
        ДатаРезультат = Дата(КаноническаяСтрока);
    Исключение
        Предупреждение("Не удалось преобразовать строку в дату: проверьте корректность введенных чисел!");
    КонецПопытки;
КонецЕсли;

Важное примечание по режиму совместимости: Если при вызове функции СтрРазделить() система выдает синтаксическую ошибку или сообщает, что функция не обнаружена, обязательно проверьте свойство «Режим совместимости» у корневого объекта вашей конфигурации. Если этот режим установлен в значение ниже 8.3.6, данная функция будет недоступна. Ниже мы разберем, как обойти это ограничение.

Способ №2: Классический разбор фиксированными строковыми функциями (для простых случаев)

Если вы абсолютно уверены, что входная строка всегда имеет строго фиксированную длину и формат (например, ровно 8 символов «ДД.ММ.ГГ»), можно применить стандартные функции работы со строками: Лев(), Сред() и Прав().

Давайте посмотрим на пример такого кода:


ИсходнаяСтрока = "28.06.86";

День  = Лев(ИсходнаяСтрока, 2);
Месяц = Сред(ИсходнаяСтрока, 4, 2);
Год   = "19" + Прав(ИсходнаяСтрока, 2); // Вручную подставляем нужный век

// Собираем дату из составных частей
МояДата = Дата(Год + Месяц + День);

Внимание, опасность! Этот способ чрезвычайно хрупок. Достаточно пользователю или внешней системе передать дату без ведущих нулей (например, «1.06.86» или «28.6.86»), как функция Сред() начнет захватывать точки вместо цифр, а функция Прав() вернет не те символы. Итоговая сборка строки сломается, и система выбросит критическое исключение. Поэтому использовать фиксированную нарезку в реальном продакшн-коде настоятельно не рекомендуется.

Способ №3: Универсальный разбор дат переменной длины (без СтрРазделить)

Как же написать надежный код, если на старой платформе (или при включенном режиме совместимости) функция СтрРазделить() недоступна, а входящие данные могут быть разной длины (например, «1.6.86»)?

Для этого мы воспользуемся проверенным разработчиками трюком — преобразуем исходную строку в многострочный текст. Мы заменим все точки-разделители на символы перевода строки Символы.ПС, после чего сможем обращаться к каждой строчке отдельно.

Давайте разберем этот универсальный алгоритм по шагам:


ДатаСтрокой = "1.6.86"; // Дата с переменной длиной сегментов

// Превращаем строку с точками в многострочный текст
МногострочныйТекст = СтрЗаменить(ДатаСтрокой, ".", Символы.ПС);

Если СтрЧислоСтрок(МногострочныйТекст) = 3 Тогда
    // Извлекаем части и очищаем от возможных случайных пробелов
    День  = СокрЛП(СтрПолучитьСтроку(МногострочныйТекст, 1));
    Месяц = СокрЛП(СтрПолучитьСтроку(МногострочныйТекст, 2));
    Год   = СокрЛП(СтрПолучитьСтроку(МногострочныйТекст, 3));
    
    // Дописываем недостающие ведущие нули для дня и месяца
    День  = ?(СтрДлина(День) = 1, "0" + День, День);
    Месяц = ?(СтрДлина(Месяц) = 1, "0" + Месяц, Месяц);
    
    // Обрабатываем двузначный год
    Если СтрДлина(Год) = 2 Тогда
        Год = ?(Год > "30", "19" + Год, "20" + Год);
    КонецЕсли;
    
    // Собираем безопасную системную строку ГГГГММДД
    Попытка
        ДатаРезультат = Дата(Год + Месяц + День);
        // Теперь у нас есть полноценная Дата, которую можно форматировать как угодно:
        СтрокаДляВывода = Формат(ДатаРезультат, "ДФ=dd.MM.yyyy");
    Исключение
        Сообщить("Ошибка при преобразовании даты!");
    КонецПопытки;
КонецЕсли;

Этот подход абсолютно надежен: он работает на любой версии платформы 1С, корректно обрабатывает отсутствие ведущих нулей и страхует от падения программы при нестандартном вводе.

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

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

Посмотрим, как решить нашу задачу буквально одной строкой кода:


ДатаСтрокой = "28.06.86";
ДатаРезультат = СтроковыеФункцииКлиентСервер.СтрокаВДату(ДатаСтрокой);

Эта функция из общего модуля БСП самостоятельно выполнит все необходимые проверки, корректно определит век для двузначного года, справится с нестандартными разделителями (точками, слэшами, дефисами) и вернет валидное значение типа Дата.

Важное предупреждение: Опасность локальных форматов и региональных настроек

В процессе обсуждений на форумах нередко можно встретить совет использовать прямое приведение типов вида Дата("28.06.1986"). Платформа 1С действительно умеет распознавать локальный формат даты текущего компьютера. Однако использовать такой подход в промышленной разработке крайне опасно.

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

  1. Если код выполняется на клиенте под управлением русскоязычной Windows, преобразование пройдет успешно.
  2. Если этот же код запустится на сервере приложений под управлением Linux или англоязычной версии Windows Server с настройками по умолчанию, система будет ожидать формат даты вида «MM/DD/YYYY». Передача строки «28.06.1986» вызовет фатальный сбой процесса с ошибкой: «Преобразование значения к типу Дата не может быть выполнено».

Золотое правило разработчика 1С: При ручном преобразовании строк в тип Дата всегда приводите строку к универсальному каноническому формату "ГГГГММДД" (или "ГГГГММДДЧЧММСС"). Данный формат является кроссплатформенным стандартом для ядра платформы 1С и гарантированно отработает на любых серверах и клиентах, независимо от установленных региональных стандартов операционной системы.

← На главную