При загрузке данных из внешних источников, таких как файлы Excel, CSV или текстовые документы, разработчики часто сталкиваются с ситуацией, когда дата представлена в виде обычной строки (например, "18.03.2019"). Попытка использовать стандартный конструктор Дата() напрямую к такой строке часто приводит к ошибке: «Преобразование к типу Дата не может быть выполнено». Это происходит потому, что встроенная функция ожидает строку в строго определенном каноническом формате или объект другого типа.
В этой статье мы подробно разберем несколько надежных способов решения этой задачи, проанализируем, почему возникают ошибки, и научимся обрабатывать нестандартные ситуации, которые могут возникнуть при работе с пользовательскими данными.
Прежде всего, выясним причину проблемы. Функция Дата() в 1С может принимать либо числа (год, месяц, день, час, минута, секунда), либо строку в формате "ГГГГММДДччммсс". Если мы передаем строку с точками, например, "18.03.2019", платформа не может автоматически определить, какой фрагмент отвечает за год, а какой — за день, особенно если региональные настройки системы отличаются от формата данных в файле.
Проанализируем самый классический метод. Если формат входной строки строго фиксирован (всегда ДД.ММ.ГГГГ), мы можем «разрезать» строку на части и передать их в конструктор даты как числа. Рассмотрим пример кода:
ДатаСЛиста = "18.03.2019"; // Исходная строка
// Извлекаем части даты:
// Прав(ДатаСЛиста, 4) - берет 4 символа справа (год)
// Сред(ДатаСЛиста, 4, 2) - берет 2 символа, начиная с 4-й позиции (месяц)
// Лев(ДатаСЛиста, 2) - берет 2 символа слева (день)
Рез = Дата(Число(Прав(ДатаСЛиста, 4)), Число(Сред(ДатаСЛиста, 4, 2)), Число(Лев(ДатаСЛиста, 2)));
Важный момент: использование функции Число() внутри конструктора Дата() гарантирует, что платформа получит именно числовые параметры, что исключает ошибки типизации.
Этот метод более современный и гибкий. Он отлично подходит, если разделители могут меняться или если вы хотите сделать код более читаемым. Разберем его по шагам:
ДатаСтрокой = "18.03.2019";
МассивЧастейДаты = СтрРазделить(ДатаСтрокой, ".");
// МассивЧастейДаты[0] - "18"
// МассивЧастейДаты[1] - "03"
// МассивЧастейДаты[2] - "2019"
Рез = Дата(МассивЧастейДаты[2], МассивЧастейДаты[1], МассивЧастейДаты[0]);
Этот способ удобен тем, что если в будущем формат даты сменится на "18/03/2019", вам достаточно будет изменить только один символ в функции СтрРазделить.
Как мы уже упоминали, 1С «понимает» строку без разделителей. Посмотрим на пример, как можно быстро преобразовать "18.03.2019" в "20190318000000". Это можно сделать комбинированием функций или простым добавлением времени, если формат строки позволяет системе распознать его (иногда срабатывает добавление пустых часов).
// Пример быстрого приведения к формату ГГГГММДД
ИсходнаяДата = "18.03.2019";
ГодЧасть = Прав(ИсходнаяДата, 4);
МесяцЧасть = Сред(ИсходнаяДата, 4, 2);
ДеньЧасть = Лев(ИсходнаяДата, 2);
КаноническаяСтрока = ГодЧасть + МесяцЧасть + ДеньЧасть + "000000";
Результат = Дата(КаноническаяСтрока);
Существует «скрытый» и очень эффективный способ преобразования, если ваша строка близка к формату ISO (ГГГГ-ММ-ДД). Функция XMLЗначение работает крайне быстро, так как использует низкоуровневые механизмы платформы.
// Если мы предварительно заменим точки на дефисы и переставим год в начало
ДатаДляXML = "2019-03-18";
Результат = XMLЗначение(Тип("Дата"), ДатаДляXML);
Хотя этот метод требует предварительной подготовки строки, он считается одним из самых «чистых» с точки зрения архитектуры платформы.
Часто проблема со строками возникает при чтении файлов Excel. Проанализируем ситуацию: если ячейка в Excel визуально выглядит как "18.03.2019", она может быть либо текстом, либо датой с особым форматом отображения.
Совет: При использовании COM-объекта (Excel.Application), всегда старайтесь обращаться к свойству Value, а не Text. Свойство Value вернет вам уже готовый объект типа Дата, и преобразование не потребуется. Если же вы используете Value2, вы получите число (количество дней с начала эпохи Excel), которое также можно конвертировать в дату 1С простым сложением.
Выясним причину, по которой даже самый идеальный код может дать сбой. Пользователи могут вводить даты как угодно: "18.03.19", "18/03/2019", "18 марта 2019". Чтобы ваша обработка не «падала», обязательно используйте конструкцию Попытка ... Исключение.
Попытка
// Здесь ваш код разбора строки
КонечнаяДата = Дата(Год, Месяц, День);
Исключение
Сообщить("Не удалось распознать дату в строке: " + СтрокаИзФайла);
// Можно установить значение по умолчанию или пропустить строку
КонечнаяДата = '00010101';
КонецПопытки;
Рекомендация: Для повышения надежности можно предварительно нормализовать строку, заменив все возможные разделители (слеши, тире) на точки с помощью функции СтрЗаменить, а уже затем приступать к разбору одним из вышеописанных методов. Это позволит обработать 90% случаев некорректного ввода данных пользователями.
Подведем итог: наиболее универсальным и надежным методом для программиста 1С остается ручная сборка даты из частей (Способ 1 и Способ 2), так как она дает полный контроль над процессом и не зависит от региональных настроек сервера или клиентского компьютера.