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

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

В этой статье мы разберем основные способы выполнения арифметических операций над датами непосредственно внутри текста запроса. Мы рассмотрим как стандартные средства платформы, так и возможности СУБД, на которой развернута 1С:Предприятие. Также уделим внимание нюансам, связанным с високосными годами и переходом через границы месяцев.

Основной метод: функция ДобавлениеВремя

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

Функция принимает три аргумента: дату, числовое значение интервала и строковое обозначение периода. Это позволяет гибко управлять вычислениями, добавляя секунды, минуты, часы, дни, месяцы или годы.

⚠️ Внимание: При сложении месяцев функция автоматически корректирует день, если в resulting месяце такого дня нет. Например, при добавлении одного месяца к 31 января получится 28 или 29 февраля, а не 1 марта.

Рассмотрим практический пример использования функции в тексте запроса. Допустим, нам необходимо найти все документы, срок оплаты которых наступит через 10 дней от текущей даты документа.

ВЫБРАТЬ

РеализацияТоваровУслуг.Ссылка КАК Ссылка,

РеализацияТоваровУслуг.Дата КАК ДатаДокумента,

ДОБАВЛЕНИЕВРЕМЯ(РеализацияТоваровУслуг.Дата, 10, ДЕНЬ) КАК ДатаОплаты

ИЗ

Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

ГДЕ

РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода

В данном примере мы создаем виртуальное поле ДатаОплаты, которое вычисляется «на лету» сервером базы данных. Это позволяет отфильтровать результаты или вывести их в отчете без необходимости дополнительной обработки в коде 1С. Использование ДобавлениеВремя гарантирует, что запрос будет выполнен эффективно.

📊 Какую единицу времени вы чаще всего используете при сложении дат?
Дни
Месяцы
Часы
Годы

Использование функции ДатаВремя для констант

Иногда требуется сложить дату с фиксированным значением или сформировать конкретную дату внутри запроса для сравнения. Для этого используется функция ДатаВремя. Она позволяет сконструировать объект даты из отдельных числовых компонентов: года, месяца, дня, часа, минуты и секунды.

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

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

ВЫБРАТЬ

РегистрНакопления.Продажи.Период,

РегистрНакопления.Продажи.Сумма

ИЗ

РегистрНакопления.Продажи КАК Продажи

ГДЕ

Продажи.Период < ДАТАВРЕМЯ(ГОД(&Период), 3, 31, 23, 59, 59)

Здесь мы явно задаем границы периода. Если бы нам нужно было сдвинуть эту границу, мы бы обернули функцию ДатаВремя в функцию ДобавлениеВремя. Комбинирование этих функций дает полный контроль над временной шкалой в ваших выборках.

💡

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

Специфика работы с месяцами и годами

Сложение месяцев и лет несет в себе скрытые риски, связанные с различной длиной календарных периодов. Когда вы добавляете месяц к дате, система должна определить, какой день будет результирующим. Логика платформы 1С следует правилу «последнего дня месяца».

Если вы добавляете месяц к 31 января, результат будет 28 февраля (или 29 в високосный год). Это поведение может быть неочевидным для новичков, ожидающих получения 1 марта или ошибки. Понимание этой логики необходимо при расчете сроков договоров, арендных платежей или сроков годности продукции.

Исходная дата Операция Результирующая дата Комментарий
31.01.2023 + 1 месяц 28.02.2023 Февраль короче января
31.01.2026 + 1 месяц 29.02.2026 Високосный год
30.01.2023 + 1 месяц 28.02.2023 30 февраля не существует
29.02.2026 + 1 год 28.02.2026 Следующий год не високосный

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

Почему 30 января + 1 месяц = 28 февраля?

Платформа 1С стремится сохранить номер дня месяца. Так как в феврале нет 30-го числа, система выбирает последний доступный день месяца — 28-е или 29-е число.

Альтернативные методы через СУБД

В некоторых случаях, особенно при работе с большими объемами данных или специфическими требованиями к производительности, разработчики обращаются к нативным функциям СУБД. Для Microsoft SQL Server это функция DATEADD, а для PostgreSQL — операторы интервалов. Использование этих методов делает запрос зависимым от типа базы данных.

Применение нативных функций СУБД оправдано, когда стандартные средства 1С не обеспечивают требуемой скорости или функциональности. Однако это усложняет поддержку конфигурации, так как при смене платформы (например, с MSSQL на PostgreSQL) запросы придется переписывать.

Пример использования функции SQL Server внутри запроса 1С (требуется режим совместимости или прямой текст запроса):

ВЫБРАТЬ

Справочник.Номенклатура.Наименование,

DATEADD(DAY, 14, Справочник.Номенклатура.ДатаСоздания) КАК ДатаКонтроля

ИЗ

Справочник.Номенклатура

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

⚠️ Внимание: Использование нативных функций СУБД нарушает принцип независимости кода 1С от платформы. Рекомендуется использовать этот метод только в исключительных случаях и документировать такие места в коде.

☑️ Проверка запроса перед внедрением

Выполнено: 0 / 4

Обработка NULL значений и ошибок

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

Для обработки таких ситуаций используется функция ЕСТЬNULL. Она позволяет подменить пустое значение на заданное по умолчанию, например, на начало эпохи или текущую дату, прежде чем выполнять операцию сложения. Это обеспечивает стабильность работы алгоритмов выборки.

Пример безопасного сложения с обработкой пустых дат:

ВЫБРАТЬ

ЗаказКлиента.Ссылка,

ДОБАВЛЕНИЕВРЕМЯ(ЕСТЬNULL(ЗаказКлиента.ДатаИсполнения, '00010101'), 5, ДЕНЬ) КАК ПлановаяДата

ИЗ

Документ.ЗаказКлиента

В этом примере, если дата исполнения не заполнена, мы берем условную минимальную дату и прибавляем к ней 5 дней. В реальном сценарии вместо минимальной даты лучше использовать дату создания документа или текущую дату, в зависимости от бизнес-смысла.

💡

Всегда используйте функцию ЕСТЬNULL при работе с датами в вычисляемых полях, чтобы избежать потери строк с незаполненными реквизитами.

Оптимизация производительности запросов

Вычисления дат непосредственно в условии отбора (в секции ГДЕ) могут негативно сказаться на производительности запроса. Если вы применяете функцию к полю таблицы, сервер баз данных часто не может использовать индекс по этому полю, что приводит к полному сканированию таблицы.

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

Сравнение двух подходов:

  • 🚫 Плохо: ГДЕ ДобавлениеВремя(Дата, 1, День) > &Граница — индекс по полю Дата не используется.
  • Хорошо: ГДЕ Дата > &ВычисленнаяГраница — индекс используется полностью.

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

⚠️ Внимание: Интерфейсы и возможности оптимизации запросов могут меняться в новых версиях платформы 1С. Рекомендуется сверять рекомендации по производительности в официальной документации к вашей версии конфигурации.

Часто задаваемые вопросы (FAQ)

Можно ли использовать оператор «+» для сложения даты и числа в запросе 1С?

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

Как добавить к дате определенное количество рабочих дней, исключая выходные?

Встроенными средствами запроса 1С это сделать невозможно, так как календарь рабочих дней хранится в регистрах сведений или внешних источниках. Для такой задачи необходимо использовать циклы в коде 1С или создавать сложные временные таблицы с calendario рабочих дней.

Влияет ли часовой пояс на результат функции ДобавлениеВремя в запросе?

Функция работает с хранящимся в базе значением даты и времени. Часовые пояса учитываются на уровне интерфейса пользователя и свойств сеанса. В тексте запроса вы оперируете «чистым» временем, записанным в таблице, без автоматической конвертации поясов.

Что вернет запрос, если при сложении месяцев получится несуществующая дата?

Система автоматически скорректирует дату до последнего дня соответствующего месяца. Например, 31 марта + 1 месяц = 30 апреля. Ошибки не возникнет, вычисление пройдет успешно с логической корректировкой дня.