Разработка и Конфигурация · 12 мин
1С: как сложить две даты и прибавить время к дате
Как в 1С сложить дату с числом, прибавить дни, месяцы и годы: функция ДобавитьКДате, РазностьДат, работа в запросах и типичные ошибки разработчиков.
Встроенный язык 1С не позволяет напрямую написать выражение вида Дата1 + Дата2 — такая операция логически бессмысленна, и платформа её не поддерживает. Зато можно прибавить к дате число секунд простым оператором «плюс», а для корректного добавления дней, месяцев и лет использовать специальную функцию ДобавитьКДате().
Путаница возникает из-за того, что под «сложением дат» разные пользователи понимают разные задачи: прибавить к дате несколько дней, вычислить срок оплаты, получить дату окончания договора или найти разницу между двумя датами. Каждая из этих задач решается своим инструментом, и выбор неправильного приводит к ошибкам в учёте — например, к неверной дате отгрузки или просрочке платежа.
Ниже разобраны все рабочие способы: оператор сложения с секундами, функции ДобавитьКДате() и РазностьДат(), аналогичные возможности в языке запросов, а также типичные ошибки и способы проверки результата.
Почему нельзя сложить две даты напрямую
Дата в 1С — это момент времени, а не число. Сложение двух моментов времени не имеет прикладного смысла: нельзя «сложить» 10 января и 15 марта так же, как нельзя сложить два адреса. Попытка выполнить Дата1 + Дата2 приведёт к ошибке исполнения, потому что платформа ожидает с правой стороны число.
Зато осмысленны две другие операции. Первая — прибавить к дате интервал (число секунд, дней, месяцев): результатом будет новая дата. Вторая — вычислить разность между датами: результатом будет число (длительность интервала). Именно эти две операции покрывают все практические задачи, которые обычно называют «сложением дат».
Способ 1: прибавить к дате число секунд оператором «+»
Самый простой вариант — арифметический. К значению типа «Дата» можно прибавить целое число, и платформа трактует его как количество секунд. Например, НоваяДата = ДатаДокумента + 3600; сдвинет дату на один час вперёд.
Чтобы прибавить сутки, нужно умножить 24 часа на 60 минут и на 60 секунд — получится 86 400 секунд. Выражение ДатаДокумента + 7 * 86400 даст дату через неделю. Для читаемости кода такие вычисления лучше оформлять через переменные с понятными именами, а не оставлять «магические числа».
У способа есть ограничение: он корректно работает только с фиксированными интервалами — секундами, минутами, часами, сутками. Прибавить таким образом «ровно один месяц» нельзя, потому что месяцы имеют разную длину: 28, 29, 30 или 31 день. Для месяцев и лет нужен другой инструмент.
// Прибавляем 10 дней к дате документа
СекундВСутках = 24 <em> 60 </em> 60; // 86400
ДатаОплаты = ДатаДокумента + 10 <em> СекундВСутках;
// Прибавляем 2 часа
ДатаНапоминания = ТекущаяДатаСеанса() + 2 </em> 3600;Способ 2: функция ДобавитьКДате() для дней, месяцев и лет
Функция ДобавитьКДате(ИсходнаяДата, ТипДобавления, Количество) — стандартный способ арифметики с календарными периодами. Второй параметр задаёт единицу измерения: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД, ДЕКАДА, ПОЛУГОДИЕ. Третий параметр — целое число, положительное или отрицательное.
Пример: ДатаОкончания = ДобавитьКДате(ДатаНачала, МЕСЯЦ, 3); вернёт дату ровно через три месяца. Важная особенность: функция корректно обрабатывает границы месяцев. Если прибавить месяц к 31 января, результатом будет последний день февраля, а не «несуществующее» 31 февраля — платформа автоматически подгоняет день под длину месяца.
Отрицательное количество работает как вычитание: ДобавитьКДате(ДатаОтгрузки, ДЕНЬ, -5) вернёт дату за пять дней до отгрузки. Это удобно для расчёта дат напоминаний, сроков подготовки документов и плановых дат закупок.
// Дата окончания договора — через 1 год
ДатаОкончания = ДобавитьКДате(ДатаЗаключения, ГОД, 1);
// Срок оплаты — 14 календарных дней
СрокОплаты = ДобавитьКДате(ДатаСчета, ДЕНЬ, 14);
// Дата за 3 месяца до текущей
НачалоПериода = ДобавитьКДате(ТекущаяДатаСеанса(), МЕСЯЦ, -3);Способ 3: вычислить разницу между датами функцией РазностьДат()
Если задача обратная — узнать, сколько времени прошло между двумя датами, — используется функция РазностьДат(Дата1, Дата2, ТипРазности). Она возвращает целое число: количество полных единиц указанного типа (дней, месяцев и т.д.) между первой и второй датой.
Пример: ДнейПросрочки = РазностьДат(СрокОплаты, ТекущаяДатаСеанса(), ДЕНЬ);. Если вторая дата раньше первой, результат будет отрицательным — это удобно для проверки просрочек: положительное значение означает, что срок уже прошёл.
Обратите внимание на слово «полных»: между 10:00 понедельника и 09:00 вторника разность в днях равна нулю, потому что полные сутки ещё не прошли. Если нужна разница по календарным датам без учёта времени, предварительно отсеките время через НачалоДня() для обеих дат.
Сложение дат в запросах 1С
В языке запросов арифметика с датами реализована функциями ДОБАВИТЬКДАТЕ(Дата, ТИП, Количество) и РАЗНОСТЬДАТ(Дата1, Дата2, ТИП) — синтаксис почти совпадает со встроенным языком. Типы периодов пишутся без кавычек: ДЕНЬ, МЕСЯЦ, ГОД и т.д.
Типовой пример — отбор документов, у которых срок оплаты наступает в ближайшие три дня: в условии ГДЕ вычисляется ДОБАВИТЬКДАТЕ(Счет.Дата, ДЕНЬ, 14) и сравнивается с текущей датой. Выполнять такой расчёт на стороне запроса эффективнее, чем выгружать таблицу и перебирать её в коде.
Ограничение: в запросе нельзя комбинировать ДОБАВИТЬКДАТЕ с произвольными выражениями так же свободно, как в коде, а результат всегда имеет тип «Дата». Для сложной логики — например, учёта производственного календаря — вычисления лучше выносить во временные таблицы или выполнять в коде после выборки.
ВЫБРАТЬ
Счета.Ссылка КАК Счет,
ДОБАВИТЬКДАТЕ(Счета.Дата, ДЕНЬ, 14) КАК СрокОплаты,
РАЗНОСТЬДАТ(&ТекущаяДата, ДОБАВИТЬКДАТЕ(Счета.Дата, ДЕНЬ, 14), ДЕНЬ) КАК ДнейОсталось
ИЗ
Документ.СчетНаОплатуПокупателю КАК Счета
ГДЕ
НЕ Счета.ОплаченКак выбрать подходящий способ
Выбор инструмента зависит от того, какой интервал нужно прибавить и где выполняется расчёт. Простое правило: фиксированные короткие интервалы (секунды, часы, сутки) допустимо складывать оператором «+», а всё календарное — дни в бизнес-логике, недели, месяцы, годы — надёжнее считать через ДобавитьКДате(), чтобы не зависеть от длины конкретного месяца.
Если расчёт нужен внутри отчёта или динамического списка, используйте функции языка запросов — это быстрее и не требует обхода выборки. Если результат участвует в сложной логике с проверками и ветвлениями, выносите его в код модуля.
Как выбрать действие
Типичные ошибки и проверка результата
Самая частая ошибка — прибавление месяцев через умножение на 30 или 31 день. Такой код даёт дрейф даты: за год накапливается расхождение в несколько дней, и даты платежей «уезжают». Вторая типичная ошибка — сравнение дат с разным временем: документ с датой 15:00 не попадает в условие «до конца дня», если дату окончания задали как начало дня.
Третья группа проблем — пустые даты. Значение '00010101' (пустая дата) участвует в арифметике как обычная дата, и прибавление к ней интервала даёт осмысленный с точки зрения платформы, но бессмысленный для учёта результат. Перед расчётами проверяйте заполненность через ЗначениеЗаполнено().
После реализации расчёта обязательно проверьте его на граничных случаях: конец месяца, конец года, 29 февраля високосного года, пустая дата. Достаточно прогнать вычисление в консоли кода или в отладчике и сверить результат с календарём вручную.
Как проверить результат
Получен последний день февраля
Ошибка исполнения или дата в начале марта
Получено 28 февраля следующего года
Ошибка или 1 марта
После НачалоДня() разность равна 1
Разность равна 0 из-за неполных суток
Ветка кода отсекает пустое значение
В результате дата января 1 года
Учёт рабочих дней вместо календарных
Стандартная арифметика дат не знает о выходных и праздниках: ДобавитьКДате() прибавит пять дней, даже если все они пришлись на праздники. Для бизнес-задач вроде «отгрузка через три рабочих дня» этого недостаточно.
Решение строится на календарных графиках: в типовых конфигурациях есть регистры с данными производственного календаря, где каждому дню сопоставлено количество рабочих часов или признак рабочего дня. Алгоритм перебирает дни от исходной даты и отсчитывает нужное число рабочих. В типовых решениях часто есть готовые функции работы с графиками — проверьте общие модули конфигурации, прежде чем писать свой вариант.
Если в конфигурации уже есть общий модуль работы с календарями или графиками, ищите готовые функции там. Самописный расчёт рабочих дней часто расходится с производственным календарём, который ведут кадровики, и вызывает вопросы при сверке сроков.
Что важно запомнить
Две даты сложить нельзя — можно прибавить к дате интервал или найти разность. Секунды и часы прибавляйте оператором «+», дни и месяцы — функцией ДобавитьКДате(), разность вычисляйте РазностьДат(). Отсекайте время при сравнении календарных дат, проверяйте пустые даты и тестируйте расчёт на границах месяцев и лет.
Частые вопросы
Что будет, если написать Дата1 + Дата2 в 1С?
Платформа выдаст ошибку исполнения, потому что к значению типа «Дата» можно прибавлять только число (секунды). Определите реальную задачу: если нужен сдвиг даты — прибавляйте число или используйте ДобавитьКДате(), если нужна длительность между датами — применяйте РазностьДат().
Как прибавить к дате один месяц?
Используйте ДобавитьКДате(ИсходнаяДата, МЕСЯЦ, 1). Функция корректно обработает разную длину месяцев: от 31 января получится последний день февраля. Не заменяйте месяц на 30 дней — такой расчёт постепенно искажает даты.
Как узнать количество дней между двумя датами?
Вызовите РазностьДат(ДатаНачала, ДатаОкончания, ДЕНЬ). Функция считает полные сутки с учётом времени, поэтому для календарного подсчёта предварительно примените НачалоДня() к обеим датам.
Можно ли прибавить к дате отрицательное число дней?
Да. И оператор «+» с отрицательным числом секунд, и ДобавитьКДате() с отрицательным третьим параметром сдвигают дату назад. Например, ДобавитьКДате(Дата, ДЕНЬ, -7) вернёт дату неделю назад.
Как сложить даты в запросе, а не в коде?
В языке запросов есть функции ДОБАВИТЬКДАТЕ(Дата, ТИП, Количество) и РАЗНОСТЬДАТ(Дата1, Дата2, ТИП) с типами ДЕНЬ, МЕСЯЦ, ГОД и другими. Они работают прямо в тексте запроса и подходят для отчётов и динамических списков.
Как прибавить рабочие дни, а не календарные?
Стандартные функции этого не умеют. Нужен производственный календарь или график работы: перебирайте дни от исходной даты и отсчитывайте только рабочие по данным регистра календарей. В типовых конфигурациях для этого обычно есть готовые функции в общих модулях.