Работа с временными отрезками и планирование событий являются неотъемлемой частью автоматизации бизнес-процессов в платформе 1С. Программистам и аналитикам часто приходится сталкиваться с задачей, когда необходимо рассчитать новую дату на основе существующей, добавив к ней определенный интервал времени. Например, это может быть расчет даты оплаты счета, определение срока сдачи отчетности или планирование следующего визита клиента. Хотя на первый взгляд операция кажется тривиальной, в экосистеме 1С:Предприятие она имеет свои нюансы, связанные с типами данных и особенностями встроенного языка.
Понимание механизмов работы с датами критически важно для написания корректного кода, который не приведет к ошибкам в расчетах или неверному отображению информации в пользовательском интерфейсе. Система строго типизирована, и попытка сложить несовместимые типы данных вызовет исключение во время выполнения. В данной статье мы детально разберем, как правильно прибавлять дни к дате, какие существуют альтернативные способы решения этой задачи и на что следует обратить особое внимание при разработке.
Основной инструмент для манипуляций со временем — это стандартные функции платформы и арифметические операторы. Однако выбор конкретного метода зависит от контекста: пишете ли вы код в модуле объекта, обрабатываете данные в запросе или формируете отчет в СКД. Важно учитывать, что 1С хранит даты с точностью до секунды, и простое добавление дней может потребовать дополнительной обработки времени, если оно не должно меняться.
Основной способ сложения даты и числа
Самый прямой и часто используемый метод в языке 1С — это применение арифметического оператора сложения к переменной типа Дата и целому числу. Платформа автоматически интерпретирует число как количество дней. Синтаксис предельно прост: вы берете переменную, содержащую текущую дату, и прибавляете к ней нужное количество суток. Результатом операции будет новая переменная того же типа Дата, сдвинутая вперед по календарю.
Рассмотрим конкретный пример кода, который демонстрирует эту операцию в модуле объекта или внешней обработке. Здесь мы создаем переменную, присваиваем ей текущее время и увеличиваем значение на 10 дней. Если исходная дата была 01.01.2026 10:00:00, то после прибавления 5 дней результат будет 06.01.2026 10:00:00.
ТекущаяДата = ТекущаяДата();
НоваяДата = ТекущаяДата + 10;
Сообщить("Дата через 10 дней: " + НоваяДата);
Такой подход работает как с положительными, так и с отрицательными числами. Если вам нужно получить дату в прошлом, достаточно вычесть дни или прибавить отрицательное значение. Это универсальное решение, которое подходит для большинства сценариев программирования в конфигурациях на базе БСП или типовых решениях. Однако стоит быть осторожным при работе с большими числами, чтобы не выйти за допустимый диапазон дат, поддерживаемый системой.
⚠️ Внимание: Оператор сложения меняет только числовую часть даты. Если ваша логика требует сброса времени на начало дня (00:00:00) перед расчетом, используйте функцию
НачалоДня()заранее, иначе время суток перенесется на новую дату.
При сложении даты и числа в 1С число всегда трактуется как количество дней. Для работы с часами или минутами этот оператор не подходит напрямую.
Использование функции ДобавлениеВдату
Для тех случаев, когда требуется более явное управление единицами измерения времени или когда код должен быть максимально читаемым для других разработчиков, платформа предоставляет встроенную функцию ДобавлениеВдату. Этот метод позволяет явно указать, какую именно гранулярность времени вы хотите изменить: годы, кварталы, месяцы, недели, дни, часы, минуты или секунды. Использование именованных констант делает код самодокументируемым.
Функция принимает три аргумента: исходную дату, тип периода (константа из перечисления ПериодДатаВремя) и количество добавляемых единиц. Это особенно полезно, когда задача усложняется и нужно прибавить не просто дни, а, например, "3 месяца и 5 дней". В контексте нашей темы мы используем константу ПериодДатаВремя.День. Такой подход снижает риск ошибки, когда коллега по команде может перепутать, что означает число в выражении сложения.
ИсходнаяДата = '20230101';
// Явно указываем, что добавляем дни
НоваяДата = ДобавлениеВдату(ИсходнаяДата, ПериодДатаВремя.День, 15);
Преимущество этого метода заключается в его гибкости. Если завтра бизнес-требования изменятся и потребуется добавлять не дни, а рабочие недели, вам нужно будет заменить только одну константу в вызове функции, не переписывая всю логику вычислений. Кроме того, функция корректно обрабатывает переходы через високосные годы и границы месяцев, если вы решите изменить тип периода на ПериодДатаВремя.Месяц.
☑️ Проверка перед использованием функции
Особенности работы в запросах 1С
При написании запросов к базе данных синтаксис немного отличается от кода в модулях. В языке запросов 1С также поддерживается арифметика с датами, но важно правильно формировать выражения в конструкции ВЫБРАТЬ. Вы можете прибавлять дни к полям таблиц или к параметрам запроса непосредственно в тексте запроса. Это позволяет выполнять расчеты на стороне СУБД, что часто эффективнее для больших выборок данных.
В запросе число, прибавляемое к дате, также интерпретируется как количество дней. Однако следует учитывать, что в запросах нельзя использовать функции языка 1С, такие как ДобавлениеВдату, внутри текста запроса (за исключением некоторых версий платформы и специфических настроек, но лучше полагаться на стандартную арифметику). Для сложных расчетов лучше использовать временные таблицы или выносить логику в код обработки результатов запроса.
| Операция | Синтаксис в запросе | Результат |
|---|---|---|
| Прибавить 1 день | Дата + 1 |
Завтрашняя дата |
| Отнять 5 дней | Дата - 5 |
Дата 5 дней назад |
| Разница в днях | Дата2 - Дата1 |
Число дней между датами |
| Сложное выражение | (Дата + 10) + 5 |
Дата + 15 дней |
Важно помнить про приоритет операций. Если вы комбинируете сложение дат с другими арифметическими действиями или функциями преобразования типов, используйте скобки для явного указания порядка вычислений. Ошибки в запросах часто возникают из-за того, что разработчик пытается прибавить дату к строке или не учитывает тип возвращаемого значения в виртуальной таблице.
Учет выходных и производственных календарей
В реальной бизнес-среде простое прибавление календарных дней часто бывает недостаточно. Логистам, бухгалтерам и менеджерам проектов важно учитывать рабочие дни. Если к дате отгрузки прибавить 3 дня, и этот период выпадет на выходные или праздники, срок сдвинется. В 1С для решения таких задач используются объекты работы с производственными календарями, хотя они и не являются частью ядра платформы "из коробки" во всех конфигурациях.
Стандартная арифметика Дата + N не знает о выходных. Она бездумно сдвигает дату по календарной сетке. Если вам требуется реализовать логику "прибавить N рабочих дней", вам придется писать циклический алгоритм. Суть его заключается в последовательном прибавлении одного дня с проверкой: является ли полученная дата рабочим днем согласно заданному календарю. Если нет — продолжаем прибавлять, пока не наберем нужное количество рабочих суток.
⚠️ Внимание: Алгоритм перебора дней в цикле может быть медленным при больших объемах данных. Не используйте его внутри запросов или в циклах по большим выборкам документов. Лучше выносить расчет в отдельные регистры или использовать предзаполненные календари.
Для реализации проверки на выходной день можно использовать встроенные функции определения дня недели или обращаться к специальным регистрам сведений, где хранится информация о производственном календаре предприятия. В типовых конфигурациях, таких как "Управление торговлей" или "ERP", часто есть готовые общие модули для работы с календарями, которые стоит использовать вместо написания велосипедов.
Обработка пустых значений и ошибок типов
Одной из самых частых причин сбоев в работе скриптов 1С является попытка выполнить арифметическую операцию с пустым значением (Null). Если переменная типа Дата не заполнена (равна Неопределено), то попытка прибавить к ней число вызовет исключение ОперацияНеподдерживается или приведет к некорректному результату в зависимости от контекста выполнения. Поэтому защита от пустых значений — обязательный этап программирования.
Перед выполнением операции сложения всегда проверяйте переменную на заполненность. Это можно сделать с помощью стандартной функции ЗначениеЗаполнено() или простого сравнения. Игнорирование этой проверки в пользовательском коде может привести к тому, что документ не проведется, а отчет не сформируется, что вызовет негативную реакцию пользователей.
Если ЗначениеЗаполнено(ИсходнаяДата) Тогда
ПлановаяДата = ИсходнаяДата + 7;
Иначе
ПлановаяДата = Неопределено; // Или текущая дата по умолчанию
КонецЕсли;
Также стоит упомянуть о типах данных. Убедитесь, что вы пытаетесь прибавить именно числовой тип. Если количество дней хранится в строковой переменной (например, пришло из внешнего файла или ввода пользователем), его необходимо предварительно преобразовать к типу Число с помощью функции Число(). Попытка сложить дату и строку "5" завершится ошибкой выполнения.
Что будет, если прибавить дробное число?
Если вы прибавите к дате число с дробной частью, например 1.5, система интерпретирует это как 1 день и 12 часов. Целая часть — дни, дробная — доля суток.
Специфика работы в Системе Компоновки Данных (СКД)
При разработке отчетов в СКД логика вычислений переносится на уровень настроек схемы компоновки. Здесь вы не пишете код в привычном виде, а настраиваете вычисляемые поля. Чтобы прибавить дни к дате в отчете, необходимо создать новое вычисляемое поле и в качестве выражения указать формулу сложения. Синтаксис выражений СКД во многом повторяет язык запросов.
В конструкторе выражений вы выбираете поле-основание (например, ДатаДокумента) и добавляете к нему числовое значение или другое поле, содержащее срок. Важно следить за типом результата. Если система не может автоматически определить тип, возможно, потребуется явное приведение типов, хотя для операции Дата + Число это обычно не требуется. Ошибки в СКД часто проявляются в виде пустых ячеек в макете отчета.
Если логика расчета сложная и зависит от множества условий, которые трудно описать одним выражением СКД, рекомендуется выносить расчет в виртуальную таблицу запроса или во временное таблицу в модуле объекта отчета. Это делает настройку отчета проще и облегчает отладку. Помните, что производительность отчета напрямую зависит от того, где именно производятся вычисления: на стороне базы данных или клиентского приложения.
В СКД используйте вычисляемые поля для простых сдвигов дат, а сложную логику с календарями выносите в запрос или программный код перед формированием отчета.
Можно ли прибавить к дате время (часы и минуты)?
Да, можно. Поскольку сутки равны 1, то один час равен 1/24, а одна минута 1/(24*60). Вы можете прибавить дробное число, например Дата + 0.5 прибавит 12 часов. Однако для читаемости кода лучше использовать функцию ДобавлениеВдату с указанием периода ПериодДатаВремя.Час или ПериодДатаВремя.Минута.
Что произойдет при переходе через високосный год?
Платформа 1С автоматически учитывает високосные годы. Если вы прибавите 365 дней к дате 01.01.2023, вы получите 01.01.2026. Если прибавите 366 дней, то 02.01.2026. Внутренний механизм хранения дат (как количество секунд от начала эры) гарантирует корректность календарных расчетов без участия программиста.
Как вычесть дни из даты?
Для вычитания дней используется тот же оператор сложения, но с отрицательным числом. Например, Дата - 10 или Дата + (-10). Также можно использовать функцию ДобавлениеВдату, передав отрицательное значение в третьем параметре. Оба способа дают идентичный результат.
Почему дата в запросе отличается от даты в коде?
Чаще всего это связано с часовыми поясами или разным представлением времени (время сервера против времени клиента). В запросах даты часто хранятся по времени сервера базы данных. Убедитесь, что вы используете функцию Сеанс.ЧасовойПояс() для корректного преобразования при необходимости синхронизации с локальным временем пользователя.