Почему функция НАЧАЛОПЕРИОДА возвращает пустую дату в запросах на 1С 8.3.13 (64-бит)?

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

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

Суть проблемы и условия её возникновения

Проанализируем ситуацию: после обновления платформы до версии 8.3.13.1513 в коде запросов, где используется стандартная функция НАЧАЛОПЕРИОДА(), система начинает возвращать «пустую» дату (01.01.0001). Примечательно, что проблема проявляется избирательно. Рассмотрим ключевые факторы, при которых возникает ошибка:

  1. Разрядность сервера: Ошибка наблюдается исключительно на 64-битной версии сервера «1С:Предприятия» (процессы rphost). На 32-битных серверах той же версии всё работает корректно.
  2. Тип СУБД: Проблема специфична для связки с Microsoft SQL Server (преимущественно версий 2012 и 2014).
  3. Параметр периодичности: Глюк проявляется при использовании параметров ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. При этом использование параметра ЧАС зачастую отрабатывает без ошибок.

Представим типовой запрос, который в данной версии платформы вернет пустую колонку «НачалоДня»:


ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(Документ.Дата, ДЕНЬ) КАК НачалоДня
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ

Почему это происходит? Технический анализ

Разберем внутренние механизмы работы платформы. Язык запросов 1С является декларативным. Когда мы пишем запрос, сервер 1С транслирует его в специфический диалект SQL, понятный конкретной СУБД (в нашем случае T-SQL для MS SQL Server). Для функции НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) платформа генерирует сложную конструкцию с использованием функций DATEADD и DATEDIFF.

Выясним причину сбоя: в релизе 8.3.13.1513 для 64-битных систем была допущена ошибка в алгоритме генерации этого SQL-кода. Из-за некорректного приведения типов или вычисления смещения дат, SQL-сервер получает на вход параметры, которые приводят к обнулению результата. Вместо ожидаемой даты SQL возвращает минимальное значение, которое 1С интерпретирует как пустую дату.

Интересен тот факт, что параметр ЧАС использует другой математический алгоритм преобразования внутри SQL-запроса, поэтому он остается работоспособным. Это часто вводит разработчиков в заблуждение, заставляя искать ошибку в данных, а не в платформе.

Решение проблемы №1: Обновление платформы

Самый правильный и надежный способ — это уход с проблемного релиза. Фирма «1С» признала данную ошибку (зарегистрирована под номером 10204734) и оперативно выпустила исправления. Рассмотрим, на какие версии стоит ориентироваться:

Как отмечают пользователи, многие переходили на 8.3.13.1513 ради оптимизированной реструктуризации базы данных (особенно для крупных баз объемом 600 Гб и выше). Если это ваш случай, помните, что исправительные релизы сохраняют все преимущества оптимизации реструктуризации, но при этом лишены багов с датами.

Решение проблемы №2: Программный обход (Workaround)

Если по каким-то организационным или техническим причинам обновить платформу прямо сейчас невозможно (например, период отчетности или жесткий регламент обновлений), мы можем изменить текст запроса так, чтобы заставить сервер генерировать другой SQL-код. Проанализируем способ замены функции НАЧАЛОПЕРИОДА.

Вместо стандартной функции можно использовать математический расчет через разность дат в секундах. Посмотрим на пример кода:


ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), Документ.Дата, ДЕНЬ) * 86400) КАК НачалоДня
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ

Разберем, как это работает:

  1. Мы вычисляем количество полных дней, прошедших с начала эры (01.01.0001) до даты документа с помощью РАЗНОСТЬДАТ(..., ДЕНЬ).
  2. Умножаем полученное количество дней на 86400 (количество секунд в сутках).
  3. Добавляем полученное количество секунд к пустой дате.

Такая конструкция транслируется в SQL совершенно иначе и не подвержена ошибке 64-битного сервера в данном релизе. Однако помните, что такой код менее читаем и его стоит использовать только как временную меру.

Дополнительные рекомендации по релизу 8.3.13.1513

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

Важный совет: Если вы столкнулись с пустой датой в запросах на 64-битном сервере 1С, не пытайтесь «чинить» базу данных через тестирование и исправление (ТиИ). Это чисто платформенный баг, который не повреждает данные в таблицах SQL, а лишь некорректно их отображает при получении. Единственным системным решением является установка исправленного релиза платформы.

Подведем итог: использование версии 8.3.13.1513 в промышленной эксплуатации на 64-битных серверах крайне нежелательно. Если вы уже столкнулись с описанным поведением НАЧАЛОПЕРИОДА(), планируйте технологическое окно для обновления платформы до версии 8.3.13.1644 или актуальных сборок старших веток.

← На главную