Как преобразовать дату из строки в нужный формат в 1С?

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

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

Исходная задача звучала так: есть дата в формате ддММгггг, и ее нужно перевести в формат ггггММдд ччммсс. Однако в ходе диалога выяснилось, что на самом деле исходные данные — это строка вида "31.08.2012 0:00:00", которую нужно подготовить для использования в запросе, ожидающем формат ДАТАВРЕМЯ(гггг, мм, дд).

Проанализируем шаги и методы, которые помогут решить эту и подобные задачи.

Решение 1: Преобразование строки в дату и форматирование

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

Шаг 1: Преобразование строки в тип `Дата`

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

Шаг 2: Форматирование даты в нужную строку

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

Посмотрим на итоговый код:


// Исходные данные
ВашаПеременная = "31.08.2012 0:00:00";

// Сначала преобразуем строку в тип Дата
ПромежуточнаяДата = Дата(ВашаПеременная);

// Теперь форматируем полученную дату в целевой формат
ДатаВНужномФормате = Формат(ПромежуточнаяДата, "ДФ=""гггг.ММ.дд ЧЧ:мм:сс""");

// Результат: "2012.08.31 00:00:00"

Можно объединить эти два действия в одну строку для краткости:

ДатаВНужномФормате = Формат(Дата(ВашаПеременная), "ДФ=""гггг.ММ.дд ЧЧ:мм:сс""");

Здесь ДФ — это параметр, указывающий формат даты (Date Format). Сама форматная строка "гггг.ММ.дд ЧЧ:мм:сс" задает желаемый вид: год из 4 цифр, месяц и день из двух, а также часы, минуты и секунды.

Важный нюанс: разница между "чч" и "ЧЧ" в строке формата

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

Если вы по ошибке используете чч для времени после полудня, вы получите неверный результат. Например, 16:00 (4 часа дня) будет преобразовано в 04:00. Это особенно опасно при передаче данных в другие системы, например, в SQL Server, который ожидает 24-часовой формат. Всегда используйте ЧЧ, если вам нужен 24-часовой формат времени.

Решение 2: Ручной разбор строки для нестандартных форматов

Иногда дата приходит в виде строки без разделителей, например, "31082012". В таком случае функция Дата() может не справиться. Для таких ситуаций подходит метод ручного разбора строки с помощью функций Лев(), Сред() и Прав().

Рассмотрим пример для строки формата "ддммгггг":


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

// Выделяем компоненты даты
Год   = Прав(ИсходнаяСтрока, 4);      // "2012"
Месяц = Сред(ИсходнаяСтрока, 3, 2);   // "08"
День  = Лев(ИсходнаяСтрока, 2);       // "31"

// Собираем строку в формате, понятном для функции Дата() (ггггММдд)
СтрокаДляПреобразования = Год + Месяц + День; // "20120831"

// Преобразуем в дату
РезультатДата = Дата(СтрокаДляПреобразования);

Этот код можно записать и в одну строку, как было предложено на форуме:


РезультатДата = Дата(Прав("31082012", 4) + Сред("31082012", 3, 2) + Лев("31082012", 2));

Этот метод надежен, но применим только для строго определенных форматов строк.

Дополнительные возможности: как добавить слово "года"

Иногда требуется вывести дату в более "человеческом" формате, например, "31 августа 2012 г.". Чтобы добавить в форматную строку статический текст, его нужно заключить в одинарные кавычки. Это говорит функции Формат(), что символы внутри кавычек не нужно интерпретировать как часть шаблона даты.

Пример:


МояДата = ТекущаяДата();
// Вывод даты с добавлением "г." в конце
Результат = Формат(МояДата, "ДФ='dd MMMM yyyy ""г.""'"); // Например, "05 мая 2024 г."

Обратите внимание, что стандартная функция Формат() не умеет склонять слова (например, "год", "года", "лет"). Для этого потребуется написать собственную небольшую функцию.

Лучшая практика: передача дат в динамические запросы через параметры

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

Это неверно и опасно! Подстановка значений в текст запроса в виде строки — плохая практика по двум причинам:

  1. Ошибки форматирования. Вы рискуете получить ошибку синтаксиса SQL, если формат даты в строке не совпадет с тем, который ожидает СУБД.
  2. SQL-инъекции. Это серьезная уязвимость в безопасности, когда злоумышленник может внедрить свой вредоносный SQL-код через параметры.

Правильный и безопасный способ — всегда использовать параметры. Это работает и для динамически формируемых запросов.

Рассмотрим правильный пример:


ТекстЗапроса = "
|ВЫБРАТЬ
|    ПоступлениеТоваровУслуг.Ссылка,
|    ПоступлениеТоваровУслуг.Номер,
|    ПоступлениеТоваровУслуг.Дата
|ИЗ
|    Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
|ГДЕ
|    ИСТИНА";

// Динамически добавляем условие по дате
Если ЗначениеЗаполнено(ДатаНачала) И ЗначениеЗаполнено(ДатаОкончания) Тогда
    // В текст запроса добавляем ПАРАМЕТРЫ, а не значения!
    ТекстЗапроса = ТекстЗапроса + " И ПоступлениеТоваровУслуг.Дата МЕЖДУ &НачПериода И &КонПериода";
КонецЕсли;

Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;

// Устанавливаем значения для параметров, только если они были добавлены в текст
Если ЗначениеЗаполнено(ДатаНачала) И ЗначениеЗаполнено(ДатаОкончания) Тогда
    // Передаем значения типа Дата, а не строки!
    Запрос.УстановитьПараметр("НачПериода", НачалоДня(ДатаНачала));
    Запрос.УстановитьПараметр("КонПериода", КонецДня(ДатаОкончания));
КонецЕсли;

Результат = Запрос.Выполнить();

При таком подходе платформа 1С сама позаботится о корректной передаче значения типа Дата в СУБД. Это избавляет от всех проблем с форматированием строк и делает код чистым, читаемым и безопасным.

← На главную