БСП в 1С

Строка в дату в 1С БСП: функция СтрокаВДату и её две реализации

Коротко

Универсальный разбор — СтроковыеФункцииКлиентСервер.СтрокаВДату(Значение, ЧастьДаты): понимает разделители . / -, порядок «день-месяц-год» и «год-месяц-день», двузначный год, названия месяцев и время. Упрощённый вариант — ОбщегоНазначенияКлиентСервер.СтрокаВДату(Значение): он пробует штатное приведение платформы, а затем два порядка следования частей — ДД ММ ГГГГ и ММ ДД ГГГГ.

Ни одна из них не выбрасывает исключение: если строку разобрать не удалось, вернётся пустая дата Дата(1, 1, 1). Результат всегда проверяйте через ЗначениеЗаполнено().

Где в БСП лежат функции преобразования строки в дату

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

  • СтроковыеФункцииКлиентСервер.СтрокаВДату(Знач Значение, ЧастьДаты = Неопределено) — полноценный парсер пользовательского ввода и внешних выгрузок;
  • ОбщегоНазначенияКлиентСервер.СтрокаВДату(Знач Значение) — компактное приведение, область ПриведениеЗначения рядом с ЭтоЧисло().

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

СтроковыеФункцииКлиентСервер.СтрокаВДату: какие форматы принимает

Это основная функция БСП для разбора «грязных» строк. Порядок работы такой: значение обрезается по краям, неразрывные пробелы, переводы строк и табуляции заменяются на обычный пробел, строка переводится в верхний регистр, затем делается попытка штатного приведения через ОписаниеТипов("Дата") с квалификатором. Если платформа строку не поняла, включается ручной разбор.

// Общий модуль СтроковыеФункцииКлиентСервер, доступен на клиенте и на сервере
Д1 = СтроковыеФункцииКлиентСервер.СтрокаВДату("23.02.1980");     // 23.02.1980 00:00:00
Д2 = СтроковыеФункцииКлиентСервер.СтрокаВДату("23/02/80");       // 23.02.1980 00:00:00
Д3 = СтроковыеФункцииКлиентСервер.СтрокаВДату("2024-05-17");     // 17.05.2024 00:00:00
Д4 = СтроковыеФункцииКлиентСервер.СтрокаВДату("20240517");       // 17.05.2024 00:00:00
Д5 = СтроковыеФункцииКлиентСервер.СтрокаВДату("170524");         // 17.05.2024 00:00:00
Д6 = СтроковыеФункцииКлиентСервер.СтрокаВДату("дата: 17-05-2024 г."); // 17.05.2024 00:00:00

Если Не ЗначениеЗаполнено(Д6) Тогда
    // строку разобрать не удалось
КонецЕсли;
СтроковыеФункцииКлиентСервер.СтрокаВДату
Значениестрока вида "ДД.ММ.ГГГГ", "ДД/ММ/ГГ", "ДД-ММ-ГГ ЧЧ:ММ:СС"
ЧастьДатыЧастиДаты, по умолчанию ЧастиДаты.Дата
Дата (при неудаче — 01.01.0001)

Что фактически разбирается по коду функции:

  • Любые нецифровые разделители. Разделителем считается всё, что не цифра, поэтому 17.05.2024, 17/05/2024 и 17-05-2024 обрабатываются одинаково.
  • Мусор по краям. Перед первой и после последней цифры текст отбрасывается — "дата: 17-05-2024 г." разберётся корректно.
  • Оба порядка частей. Если первая группа цифр состоит из четырёх символов, она считается годом (2024-05-17), иначе первой идёт день (17.05.2024).
  • Двузначный год. Порог — 30: год меньше 30 трактуется как 20xx, остальные как 19xx. Так "23/02/80" становится 1980 годом, а "01.01.29" — 2029.
  • Сплошные цифры. Строка из 6 цифр читается как ДДММГГ, из 8 — сначала как ГГГГММДД, а если такой даты не существует, как ДДММГГГГ.
  • Названия месяцев. Перед разбором функция в цикле по 12 месяцам подставляет вместо названия его номер, используя шаблоны Формат(Дата, "ДФ=ММММ") и Формат(Дата, "ДФ=MMM") в верхнем регистре. Регистр исходной строки значения не имеет, а вот форма и язык названия должны совпадать с тем, что даёт платформа в текущем сеансе, — это стоит проверить на своей базе.
В ИИ Консоли кода: вставьте десяток реальных строк из вашей выгрузки и попросите агента прогнать их через обе функции БСП прямо в базе. За один запуск станет видно, какие строки превращаются в 01.01.0001 и какой модуль подходит под ваш формат, — быстрее, чем собирать обработку с ручным перебором.

Параметр ЧастьДаты: почему теряется время

Второй параметр — значение системного перечисления ЧастиДаты. Функция строит из него Новый КвалификаторыДаты(ЧастьДаты) и использует квалификатор при приведении, а заодно сама решает, разбирать ли дату и время. Если передано не значение типа ЧастиДаты, параметр молча заменяется на ЧастиДаты.Дата — то есть по умолчанию время из строки отбрасывается.

Строка = "17.05.2024 14:30:05";

// По умолчанию — только дата, время обнуляется
Д1 = СтроковыеФункцииКлиентСервер.СтрокаВДату(Строка);                      // 17.05.2024 00:00:00

// Дата и время
Д2 = СтроковыеФункцииКлиентСервер.СтрокаВДату(Строка, ЧастиДаты.ДатаВремя); // 17.05.2024 14:30:05

// Только время, дата остаётся пустой
Д3 = СтроковыеФункцииКлиентСервер.СтрокаВДату(Строка, ЧастиДаты.Время);     // 01.01.0001 14:30:05
КвалификаторыДаты
ЧастиДатыДата, Время или ДатаВремя
КвалификаторыДаты

Время в строке распознаётся как последний фрагмент после пробела. Он отделяется от даты, разбирается по разделителям на часы, минуты и секунды и приводится к виду ЧЧММСС. Отдельная проверка защищает от ложного срабатывания: фрагмент из двух или четырёх цифр без разделителей считается частью даты (например, годом), а не временем.

При ЧастиДаты.Время дата принудительно заменяется на 00010101, поэтому результат — пустая дата с нужным временем. Это удобно, когда из строки нужно вытащить только момент суток, чтобы потом прибавить его к дате документа.

ОбщегоНазначенияКлиентСервер.СтрокаВДату: упрощённое приведение

Вторая реализация короче и живёт в области ПриведениеЗначения. Сначала она проверяет заполненность строки, затем пробует привести значение штатным ОписаниеТипов("Дата").ПривестиЗначение(). Если результат — непустая дата, он и возвращается. Дальше начинается собственный разбор.

// Общий модуль ОбщегоНазначенияКлиентСервер
Д1 = ОбщегоНазначенияКлиентСервер.СтрокаВДату("17.05.2024 14:30:05"); // 17.05.2024 14:30:05
Д2 = ОбщегоНазначенияКлиентСервер.СтрокаВДату("05/17/2024");          // 17.05.2024 00:00:00
Д3 = ОбщегоНазначенияКлиентСервер.СтрокаВДату("");                    // 01.01.0001 00:00:00
Д4 = ОбщегоНазначенияКлиентСервер.СтрокаВДату("17 мая 2024");         // 01.01.0001 00:00:00
ОбщегоНазначенияКлиентСервер.СтрокаВДату
Значениестрока, не длиннее 25 символов для ручного разбора
Дата (при неудаче — 01.01.0001)

Алгоритм ручного разбора здесь такой:

  • строка длиннее 25 символов сразу даёт пустую дату;
  • из строки посимвольно набираются группы цифр; групп меньше трёх — пустая дата;
  • недостающие группы (часы, минуты, секунды) дополняются нулями до шести;
  • первая попытка — трактовка исходного порядка как ДД ММ ГГГГ: части переставляются в ГГГГММДДЧЧММСС и приводятся к дате;
  • если такой даты не существует, вторая попытка — порядок ММ ДД ГГГГ, поэтому американское 05/17/2024 тоже разберётся;
  • обе попытки провалились — возвращается Дата(1, 1, 1).

Важно: время здесь не отбрасывается — если в строке есть часы и минуты, они попадут в результат, аналога ЧастьДаты у этой функции нет. Логики достройки века тоже нет: двузначный год группа не превращает в четырёхзначный, и разбор опирается только на то, что сможет принять ОписаниеТипов.

Чем отличаются две реализации СтрокаВДату

  • Управление временем. В СтроковыеФункцииКлиентСервер время по умолчанию отбрасывается и включается через ЧастиДаты.ДатаВремя. В ОбщегоНазначенияКлиентСервер время всегда идёт в результат, если оно было в строке.
  • Двузначный год. Обрабатывается только в СтроковыеФункцииКлиентСервер (порог 30). Вторая функция такой логики не содержит.
  • Названия месяцев. Поддерживаются только в СтроковыеФункцииКлиентСервер; для второй реализации буквы — просто разделители, и строка без трёх групп цифр даст пустую дату.
  • Порядок частей. СтроковыеФункцииКлиентСервер определяет год по длине первой группы (4 цифры — год). ОбщегоНазначенияКлиентСервер перебирает два варианта: сначала ДД ММ ГГГГ, затем ММ ДД ГГГГ.
  • Ограничение длины. 25 символов — только во второй функции, и только для ветки ручного разбора.

Практический вывод: пользовательский ввод, CSV, обмен с внешними системами и любые «неизвестные» форматы разбирайте через СтроковыеФункцииКлиентСервер. Вторая функция уместна там, где формат почти нормализован, и нужно лишь подстраховаться от перестановки дня и месяца.

Что вернётся при некорректной строке

Обе функции спроектированы как «безопасные»: любое непонятное значение превращается в пустую дату Дата(1, 1, 1), то есть 01.01.0001 00:00:00. Исключение не возбуждается, лог не пишется, признака «разобрано / не разобрано» в возвращаемом значении нет. Поэтому проверка результата — обязанность вызывающего кода.

ЗначениеИзФайла = СокрЛП(Ячейка);

Дата = СтроковыеФункцииКлиентСервер.СтрокаВДату(ЗначениеИзФайла, ЧастиДаты.ДатаВремя);

Если Не ЗначениеЗаполнено(Дата) Тогда
    ТекстОшибки = СтрШаблон("Строка %1 не распознана как дата, строка файла %2",
        ЗначениеИзФайла, НомерСтроки);
    ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки);
    Продолжить;
КонецЕсли;

Отдельная ловушка — «частично разобранная» строка. Если в значении три группы цифр, разбор формально удастся, даже когда исходный формат был другим. Например, строка с номером и датой вида "12-345-2024" вернёт не пустую дату, а результат интерпретации групп как дня, месяца и года. Пустая дата ловит только полный провал разбора, а не смысловую ошибку, — сверяйте формат источника заранее.

Когда достаточно платформенных Дата() и XMLЗначение()

Если формат строки известен и стабилен, функции БСП не нужны — платформа справится быстрее и строже.

// Жёсткий формат ГГГГММДДЧЧММСС — литерал платформы
Д1 = Дата("20240517143005");        // 17.05.2024 14:30:05

// ISO 8601 из веб-сервиса или JSON: строгий разбор, ошибка формата — исключение
Попытка
    Д2 = XMLЗначение(Тип("Дата"), "2024-05-17T14:30:05");
Исключение
    Д2 = Дата(1, 1, 1);
КонецПопытки;

// Приведение по описанию типов — тот же механизм, что использует БСП внутри
ОписаниеДаты = Новый ОписаниеТипов("Дата");
Д3 = ОписаниеДаты.ПривестиЗначение("20240517");
XMLЗначение
ТипТип("Дата")
СтрокаXMLзначение в формате XML (ISO 8601)
Дата

Ориентир по выбору: XMLЗначение() — для обменов, где формат гарантирован схемой и любое отклонение должно быть ошибкой; Дата() — для собственных строк вида ГГГГММДД; ОписаниеТипов("Дата").ПривестиЗначение() — когда нужно приведение без исключения, но и без эвристик БСП. Строки со смещением часового пояса (2024-05-17T14:30:05+03:00) корректно разбирает XMLЗначение(), а не СтрокаВДату: для функций БСП знак смещения — обычный разделитель, и лишние группы цифр ломают разбор.

В ИИ Консоли кода: попросите агента написать загрузчик, который сначала пробует строгий разбор формата источника, а на нераспознанных строках откатывается к функции БСП и собирает список проблемных значений. Агент выполнит код на вашей базе и сразу покажет, сколько строк ушло в 01.01.0001.

Частые ошибки при преобразовании строки в дату в БСП

  • Ждут исключение при неверном формате. Его не будет: обе функции вернут Дата(1, 1, 1). Без проверки ЗначениеЗаполнено() в документы попадёт 01.01.0001, и обнаружится это уже в отчётах.
  • Пропало время. СтроковыеФункцииКлиентСервер.СтрокаВДату() без второго параметра работает как ЧастиДаты.Дата и обнуляет часы и минуты. Для строк с временем передавайте ЧастиДаты.ДатаВремя.
  • В ЧастьДаты передают строку или число. Значение не типа ЧастиДаты молча заменяется на ЧастиДаты.Дата. Ошибки не будет, время просто исчезнет. Плюс параметр объявлен без Знач: переданная переменная перезапишется значением ЧастиДаты.Дата в вызывающем коде.
  • Меняют модуль, не меняя ожиданий. Замена СтроковыеФункцииКлиентСервер на ОбщегоНазначенияКлиентСервер убирает поддержку двузначного года и названий месяцев, но добавляет время в результат.
  • Неоднозначность дня и месяца. Для "05.06.2024" обе функции выберут первый подходящий вариант — 5 июня. Американский порядок распознаётся, только когда день больше 12 делает первый вариант невозможным.
  • Двузначный год у дат рождения. Порог 30 в СтроковыеФункцииКлиентСервер означает, что "01.01.30" станет 1930 годом, а "01.01.29" — 2029. Для исторических дат передавайте четырёхзначный год.
  • ISO-строка с таймзоной. Смещение +03:00 добавляет лишние группы цифр и приводит к пустой дате. Такие значения разбирайте XMLЗначение(Тип("Дата"), ...).
  • Длинная строка в ОбщегоНазначенияКлиентСервер. Больше 25 символов — ручной разбор не запускается вообще, результат сразу пустая дата.

Частые вопросы про СтрокаВДату в БСП

В каком модуле БСП лежит функция преобразования строки в дату?

Их две: СтроковыеФункцииКлиентСервер.СтрокаВДату(Знач Значение, ЧастьДаты = Неопределено) и ОбщегоНазначенияКлиентСервер.СтрокаВДату(Знач Значение). Первая — универсальный парсер с поддержкой двузначного года, названий месяцев и времени, вторая — упрощённое приведение с перебором порядков ДД ММ ГГГГ и ММ ДД ГГГГ. Оба модуля доступны и на клиенте, и на сервере.

Что вернёт СтрокаВДату, если строку не удалось разобрать?

Пустую дату Дата(1, 1, 1) — 01.01.0001 00:00:00. Исключение не возбуждается, поэтому результат нужно проверять через ЗначениеЗаполнено(), иначе некорректные строки тихо превратятся в пустую дату в данных.

Когда вместо БСП достаточно платформенных Дата() и XMLЗначение()?

Когда формат строки известен заранее. Дата("ГГГГММДДЧЧММСС") подходит для собственных нормализованных строк, XMLЗначение(Тип("Дата"), ...) — для ISO 8601 из обменов, где нарушение формата должно приводить к ошибке. Функции БСП нужны там, где формат заранее неизвестен или пришёл от пользователя.

Тарифы

ИИ Консоль кода 1С

Лайт

Бесплатно
≈ 1,5 млн токенов

Для ознакомления с возможностями

  • Все функции бесплатно на 2 дня +2 дня за подписку на Telegram или Max
  • Полный набор инструментов без урезаний
  • Без ввода карты
Начать бесплатно

Старт

1990 руб. в месяц
≈ 10 млн токенов

Для индивидуального использования

Выбрать тариф

Продвинутый

Популярный выбор
3990 руб. в месяц
≈ 25 млн токенов

Для интенсивного использования или команд

  • До 15 конфигураций
  • Встроенный агент запросов 1С
  • Свои подписки Codex, Claude и любые OpenAI-совместимые
  • Внешние обработки без Конфигуратора
  • Приоритетная техническая поддержка
Выбрать тариф