К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как сложить две даты и прибавить время к дате

Как в 1С сложить дату с числом, прибавить дни, месяцы и годы: функция ДобавитьКДате, РазностьДат, работа в запросах и типичные ошибки разработчиков.

Встроенный язык 1С не позволяет напрямую написать выражение вида Дата1 + Дата2 — такая операция логически бессмысленна, и платформа её не поддерживает. Зато можно прибавить к дате число секунд простым оператором «плюс», а для корректного добавления дней, месяцев и лет использовать специальную функцию ДобавитьКДате().

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

Ниже разобраны все рабочие способы: оператор сложения с секундами, функции ДобавитьКДате() и РазностьДат(), аналогичные возможности в языке запросов, а также типичные ошибки и способы проверки результата.

Почему нельзя сложить две даты напрямую

Дата в 1С — это момент времени, а не число. Сложение двух моментов времени не имеет прикладного смысла: нельзя «сложить» 10 января и 15 марта так же, как нельзя сложить два адреса. Попытка выполнить Дата1 + Дата2 приведёт к ошибке исполнения, потому что платформа ожидает с правой стороны число.

Зато осмысленны две другие операции. Первая — прибавить к дате интервал (число секунд, дней, месяцев): результатом будет новая дата. Вторая — вычислить разность между датами: результатом будет число (длительность интервала). Именно эти две операции покрывают все практические задачи, которые обычно называют «сложением дат».

Способ 1: прибавить к дате число секунд оператором «+»

Самый простой вариант — арифметический. К значению типа «Дата» можно прибавить целое число, и платформа трактует его как количество секунд. Например, НоваяДата = ДатаДокумента + 3600; сдвинет дату на один час вперёд.

Чтобы прибавить сутки, нужно умножить 24 часа на 60 минут и на 60 секунд — получится 86 400 секунд. Выражение ДатаДокумента + 7 * 86400 даст дату через неделю. Для читаемости кода такие вычисления лучше оформлять через переменные с понятными именами, а не оставлять «магические числа».

У способа есть ограничение: он корректно работает только с фиксированными интервалами — секундами, минутами, часами, сутками. Прибавить таким образом «ровно один месяц» нельзя, потому что месяцы имеют разную длину: 28, 29, 30 или 31 день. Для месяцев и лет нужен другой инструмент.

bsl
// Прибавляем 10 дней к дате документа
СекундВСутках = 24 <em> 60 </em> 60; // 86400
ДатаОплаты = ДатаДокумента + 10 <em> СекундВСутках;

// Прибавляем 2 часа
ДатаНапоминания = ТекущаяДатаСеанса() + 2 </em> 3600;

Способ 2: функция ДобавитьКДате() для дней, месяцев и лет

Функция ДобавитьКДате(ИсходнаяДата, ТипДобавления, Количество) — стандартный способ арифметики с календарными периодами. Второй параметр задаёт единицу измерения: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД, ДЕКАДА, ПОЛУГОДИЕ. Третий параметр — целое число, положительное или отрицательное.

Пример: ДатаОкончания = ДобавитьКДате(ДатаНачала, МЕСЯЦ, 3); вернёт дату ровно через три месяца. Важная особенность: функция корректно обрабатывает границы месяцев. Если прибавить месяц к 31 января, результатом будет последний день февраля, а не «несуществующее» 31 февраля — платформа автоматически подгоняет день под длину месяца.

Отрицательное количество работает как вычитание: ДобавитьКДате(ДатаОтгрузки, ДЕНЬ, -5) вернёт дату за пять дней до отгрузки. Это удобно для расчёта дат напоминаний, сроков подготовки документов и плановых дат закупок.

bsl
// Дата окончания договора — через 1 год
ДатаОкончания = ДобавитьКДате(ДатаЗаключения, ГОД, 1);

// Срок оплаты — 14 календарных дней
СрокОплаты = ДобавитьКДате(ДатаСчета, ДЕНЬ, 14);

// Дата за 3 месяца до текущей
НачалоПериода = ДобавитьКДате(ТекущаяДатаСеанса(), МЕСЯЦ, -3);

Способ 3: вычислить разницу между датами функцией РазностьДат()

Если задача обратная — узнать, сколько времени прошло между двумя датами, — используется функция РазностьДат(Дата1, Дата2, ТипРазности). Она возвращает целое число: количество полных единиц указанного типа (дней, месяцев и т.д.) между первой и второй датой.

Пример: ДнейПросрочки = РазностьДат(СрокОплаты, ТекущаяДатаСеанса(), ДЕНЬ);. Если вторая дата раньше первой, результат будет отрицательным — это удобно для проверки просрочек: положительное значение означает, что срок уже прошёл.

Обратите внимание на слово «полных»: между 10:00 понедельника и 09:00 вторника разность в днях равна нулю, потому что полные сутки ещё не прошли. Если нужна разница по календарным датам без учёта времени, предварительно отсеките время через НачалоДня() для обеих дат.

Сложение дат в запросах 1С

В языке запросов арифметика с датами реализована функциями ДОБАВИТЬКДАТЕ(Дата, ТИП, Количество) и РАЗНОСТЬДАТ(Дата1, Дата2, ТИП) — синтаксис почти совпадает со встроенным языком. Типы периодов пишутся без кавычек: ДЕНЬ, МЕСЯЦ, ГОД и т.д.

Типовой пример — отбор документов, у которых срок оплаты наступает в ближайшие три дня: в условии ГДЕ вычисляется ДОБАВИТЬКДАТЕ(Счет.Дата, ДЕНЬ, 14) и сравнивается с текущей датой. Выполнять такой расчёт на стороне запроса эффективнее, чем выгружать таблицу и перебирать её в коде.

Ограничение: в запросе нельзя комбинировать ДОБАВИТЬКДАТЕ с произвольными выражениями так же свободно, как в коде, а результат всегда имеет тип «Дата». Для сложной логики — например, учёта производственного календаря — вычисления лучше выносить во временные таблицы или выполнять в коде после выборки.

bsl
ВЫБРАТЬ
	Счета.Ссылка КАК Счет,
	ДОБАВИТЬКДАТЕ(Счета.Дата, ДЕНЬ, 14) КАК СрокОплаты,
	РАЗНОСТЬДАТ(&ТекущаяДата, ДОБАВИТЬКДАТЕ(Счета.Дата, ДЕНЬ, 14), ДЕНЬ) КАК ДнейОсталось
ИЗ
	Документ.СчетНаОплатуПокупателю КАК Счета
ГДЕ
	НЕ Счета.Оплачен

Как выбрать подходящий способ

Выбор инструмента зависит от того, какой интервал нужно прибавить и где выполняется расчёт. Простое правило: фиксированные короткие интервалы (секунды, часы, сутки) допустимо складывать оператором «+», а всё календарное — дни в бизнес-логике, недели, месяцы, годы — надёжнее считать через ДобавитьКДате(), чтобы не зависеть от длины конкретного месяца.

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

Маршрут решения

Как выбрать действие

Нужно прибавить часы, минуты или точное число сутокИспользуйте оператор «+» с числом секунд
Нужно прибавить месяцы, кварталы или годыИспользуйте ДобавитьКДате() — оператор «+» даст ошибку из-за разной длины месяцев
Нужно узнать, сколько дней между датамиИспользуйте РазностьДат() с типом ДЕНЬ
Расчёт нужен в отчёте или динамическом спискеПрименяйте ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ в тексте запроса
Нужно учитывать только рабочие дниИспользуйте календарные графики (регистр сведений с графиком работы), арифметика дат здесь не подходит

Типичные ошибки и проверка результата

Самая частая ошибка — прибавление месяцев через умножение на 30 или 31 день. Такой код даёт дрейф даты: за год накапливается расхождение в несколько дней, и даты платежей «уезжают». Вторая типичная ошибка — сравнение дат с разным временем: документ с датой 15:00 не попадает в условие «до конца дня», если дату окончания задали как начало дня.

Третья группа проблем — пустые даты. Значение '00010101' (пустая дата) участвует в арифметике как обычная дата, и прибавление к ней интервала даёт осмысленный с точки зрения платформы, но бессмысленный для учёта результат. Перед расчётами проверяйте заполненность через ЗначениеЗаполнено().

Типичные ошибки
01
Прибавление месяца как 30 дней — дата постепенно смещается, используйте ДобавитьКДате с типом МЕСЯЦ
02
Сравнение дат без отсечения времени — документы на границе дня выпадают из выборки, применяйте НачалоДня() или КонецДня()
03
Арифметика с пустой датой 01.01.0001 — результат формально корректен, но бессмыслен; проверяйте ЗначениеЗаполнено()
04
Попытка написать Дата1 + Дата2 — платформа выдаст ошибку; определите, что нужно на самом деле: сдвиг даты или разность
05
Игнорирование времени при расчёте просрочки — РазностьДат в днях считает полные сутки, а не календарные даты

После реализации расчёта обязательно проверьте его на граничных случаях: конец месяца, конец года, 29 февраля високосного года, пустая дата. Достаточно прогнать вычисление в консоли кода или в отладчике и сверить результат с календарём вручную.

Контрольные точки

Как проверить результат

Прибавление месяца к 31 января
Норма

Получен последний день февраля

Тревожный признак

Ошибка исполнения или дата в начале марта

Прибавление года к 29 февраля
Норма

Получено 28 февраля следующего года

Тревожный признак

Ошибка или 1 марта

Разность дат в один календарный день, но разное время
Норма

После НачалоДня() разность равна 1

Тревожный признак

Разность равна 0 из-за неполных суток

Расчёт с незаполненной датой
Норма

Ветка кода отсекает пустое значение

Тревожный признак

В результате дата января 1 года

Учёт рабочих дней вместо календарных

Стандартная арифметика дат не знает о выходных и праздниках: ДобавитьКДате() прибавит пять дней, даже если все они пришлись на праздники. Для бизнес-задач вроде «отгрузка через три рабочих дня» этого недостаточно.

Решение строится на календарных графиках: в типовых конфигурациях есть регистры с данными производственного календаря, где каждому дню сопоставлено количество рабочих часов или признак рабочего дня. Алгоритм перебирает дни от исходной даты и отсчитывает нужное число рабочих. В типовых решениях часто есть готовые функции работы с графиками — проверьте общие модули конфигурации, прежде чем писать свой вариант.

Если в конфигурации уже есть общий модуль работы с календарями или графиками, ищите готовые функции там. Самописный расчёт рабочих дней часто расходится с производственным календарём, который ведут кадровики, и вызывает вопросы при сверке сроков.
ПЗ
Практическое замечание
Итог

Что важно запомнить

Две даты сложить нельзя — можно прибавить к дате интервал или найти разность. Секунды и часы прибавляйте оператором «+», дни и месяцы — функцией ДобавитьКДате(), разность вычисляйте РазностьДат(). Отсекайте время при сравнении календарных дат, проверяйте пустые даты и тестируйте расчёт на границах месяцев и лет.

Частые вопросы

Что будет, если написать Дата1 + Дата2 в 1С?

Платформа выдаст ошибку исполнения, потому что к значению типа «Дата» можно прибавлять только число (секунды). Определите реальную задачу: если нужен сдвиг даты — прибавляйте число или используйте ДобавитьКДате(), если нужна длительность между датами — применяйте РазностьДат().

Как прибавить к дате один месяц?

Используйте ДобавитьКДате(ИсходнаяДата, МЕСЯЦ, 1). Функция корректно обработает разную длину месяцев: от 31 января получится последний день февраля. Не заменяйте месяц на 30 дней — такой расчёт постепенно искажает даты.

Как узнать количество дней между двумя датами?

Вызовите РазностьДат(ДатаНачала, ДатаОкончания, ДЕНЬ). Функция считает полные сутки с учётом времени, поэтому для календарного подсчёта предварительно примените НачалоДня() к обеим датам.

Можно ли прибавить к дате отрицательное число дней?

Да. И оператор «+» с отрицательным числом секунд, и ДобавитьКДате() с отрицательным третьим параметром сдвигают дату назад. Например, ДобавитьКДате(Дата, ДЕНЬ, -7) вернёт дату неделю назад.

Как сложить даты в запросе, а не в коде?

В языке запросов есть функции ДОБАВИТЬКДАТЕ(Дата, ТИП, Количество) и РАЗНОСТЬДАТ(Дата1, Дата2, ТИП) с типами ДЕНЬ, МЕСЯЦ, ГОД и другими. Они работают прямо в тексте запроса и подходят для отчётов и динамических списков.

Как прибавить рабочие дни, а не календарные?

Стандартные функции этого не умеют. Нужен производственный календарь или график работы: перебирайте дни от исходной даты и отсчитывайте только рабочие по данным регистра календарей. В типовых конфигурациях для этого обычно есть готовые функции в общих модулях.