Почему НачалоДня() возвращает 12:00:00 вместо 00:00:00 и как правильно выгружать дату в XML

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

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

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

Разберем причину: регистр символов имеет значение

Рассмотрим исходный код, который вызвал затруднение у автора вопроса:


ЗаписьXML.ЗаписатьТекст(XMLСтрока(Формат(НачалоДня(ТекущаяДата()), "ДФ='yyyy-MM-dd чч:мм:сс'" )));

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

В 1С символы форматной строки ДФ крайне чувствительны к регистру. Выясним разницу между ними:

  1. Символы чч (строчные) — это 12-часовой формат представления времени (от 01 до 12). В этом формате полночь (00:00:00) отображается как 12. Именно поэтому в XML-файле автора появилось значение "12:00:00".
  2. Символы ЧЧ (прописные/заглавные) — это привычный нам 24-часовой формат (от 00 до 23).

Таким образом, для решения проблемы достаточно изменить регистр букв в форматной строке. Посмотрим на исправленный вариант:


// Правильное использование 24-часового формата
Результат = Формат(НачалоДня(ТекущаяДата()), "ДФ='yyyy-MM-dd ЧЧ:мм:сс'");
// Результат: 2024-05-22 00:00:00

Оптимизация кода и избыточные преобразования

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

Рассмотрим более элегантный и правильный с точки зрения стандартов XML способ получения даты. Платформа 1С умеет самостоятельно преобразовывать дату в формат ISO 8601 (стандарт для XML), если передать объект типа Дата напрямую в функцию XMLСтрока.

Сравним два подхода:


// Подход 1: Ручное форматирование (может нарушить стандарт XML)
ЗаписьXML.ЗаписатьТекст(Формат(НачалоДня(ТекущаяДата()), "ДФ='yyyy-MM-dd ЧЧ:мм:сс'"));

// Подход 2: Использование встроенных механизмов сериализации (рекомендуется)
ЗаписьXML.ЗаписатьТекст(XMLСтрока(НачалоДня(ТекущаяДата())));

Во втором случае платформа сформирует строку вида 2024-05-22T00:00:00. Обратите внимание на символ T между датой и временем — это обязательный разделитель согласно стандарту XML. Ручное форматирование через пробел может привести к тому, что внешняя система не сможет корректно прочитать ваш файл.

Работа с часовыми поясами: ТекущаяДата vs ТекущаяДатаСеанса

Когда мы работаем с "началом дня", важно понимать, относительно какого часового пояса мы производим расчет. Выясним разницу между ключевыми функциями:

Если ваша база данных распределена по разным регионам, использование ТекущаяДата() для формирования "начала дня" может привести к логическим ошибкам. Например, если сервер находится в Москве, а пользователь во Владивостоке, начало дня по серверу наступит на 7 часов позже, чем ожидает пользователь.

Для технических обменов через XML также крайне полезно использовать универсальное время (UTC). Рассмотрим пример записи даты в формате UTC:


УниверсальнаяДата = УниверсальноеВремя(НачалоДня(ТекущаяДатаСеанса()));
ЗаписьXML.ЗаписатьТекст(XMLСтрока(УниверсальнаяДата));
// Результат будет содержать символ 'Z' в конце: 2024-05-21T21:00:00Z

Использование XDTO для автоматизации выгрузки

Чтобы избежать ручного контроля над форматами дат и временем, профессиональным стандартом в 1С является использование механизмов XDTO (XML Data Transfer Objects).

Проанализируем, почему это удобно:

  1. Если в вашей XSD-схеме тип поля определен как xs:date, то при записи значения 1С сама отсечет временную часть, и вам не придется вызывать НачалоДня.
  2. Если тип поля xs:dateTime, механизм XDTO сам позаботится о правильном формате ISO 8601 с учетом часовых поясов.

Пример записи через СериализаторXDTO:


// Предположим, у нас есть объект Дата
МояДата = НачалоДня(ТекущаяДата());
// Записываем напрямую в XML через сериализатор
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, МояДата, НазначениеТипаXML.Явное);

Подведем итоги

Мы выяснили, что "странное" поведение функции НачалоДня в 1С всегда связано не с самой функцией, а с тем, как разработчик интерпретирует результат. Основные правила, которые помогут избежать ошибок в будущем:

Соблюдение этих простых правил сделает ваш код более надежным, а интеграции с внешними системами — стабильными.

← На главную