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

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

Как складывать даты в 1С: функции и практические приёмы

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

В языке 1С дата — это не число, а отдельный тип данных, поэтому прямое сложение вида Дата + 3 не работает так, как ожидает новичок: число прибавится в секундах, а не в днях. Для корректной арифметики с датами во встроенном языке предусмотрены специальные функции, и главная из них — ДобавитьКДате().

Задача сложения дат возникает постоянно: расчёт срока оплаты по договору, дата отгрузки через N рабочих дней, окончание гарантийного срока, период хранения документов, плановая дата закрытия заказа. В зависимости от того, нужны календарные дни, месяцы или рабочие дни, выбирается разный подход.

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

Что такое дата в 1С и почему нельзя просто прибавить число

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

Из этого следует простое правило: если нужно прибавить дни, часы или минуты, либо используйте специальные функции, либо явно переводите величину в секунды. Один день — это 86400 секунд, час — 3600, минута — 60. Такое сложение безопасно для дней и меньших единиц, потому что длительность дня и часа фиксирована.

А вот для месяцев и лет сложение через секунды недопустимо: месяцы имеют разную длину (28–31 день), и платформа сама должна решить, какую дату вернуть при переходе, например, от 31 января на месяц вперёд. Для таких операций существуют отдельные механизмы.

Функция ДобавитьКДате — основной способ сложения

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

Примеры использования:

ДатаОплаты = ДобавитьКДате(ДатаДокумента, "День", 14);   // +14 календарных дней

ДатаОтгрузки = ДобавитьКДате(ДатаЗаказа, "Час", 48); // +48 часов

КонецГарантии = ДобавитьКДате(ДатаПродажи, "Год", 3); // +3 года

ПрошлаяНеделя = ДобавитьКДате(ТекущаяДата(), "Неделя", -1); // минус неделя

Важная особенность: при добавлении месяцев, кварталов и лет функция корректно обрабатывает конец месяца. Если к 31 января прибавить один месяц, результатом будет последний день февраля, а не «несуществующее» 31 февраля. Это поведение отличает функцию от наивного сложения через секунды.

1c
НоваяДата = ДобавитьКДате(ДатаНачала, "День", 10);
Если Месяц(НоваяДата) <> Месяц(ДатаНачала) Тогда
    Сообщить("Дата перешла в следующий месяц");
КонецЕсли;

Функция ДобавитьМесяц и нюансы конца месяца

Для смещения на месяцы в языке есть отдельная функция ДобавитьМесяц(Дата, КоличествоМесяцев). По сути она дублирует ДобавитьКДате(Дата, "Месяц", N), но исторически используется чаще и лучше читается в коде. Количество также может быть отрицательным.

Ключевой нюанс — поведение на границе месяца. Правило платформы: если исходный день не существует в целевом месяце, результатом становится последний день этого месяца. Так, ДобавитьМесяц('20260131', 1) вернёт 29.02.2026 (в високосном году), а не 02.03. Однако обратное смещение от 29 февраля на месяц назад даст 29 января, а не 31 — симметрии здесь нет, и это нужно учитывать в циклических расчётах.

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

Сложение через секунды: когда это допустимо

Для единиц меньше месяца допустимо прямое сложение с переводом в секунды. Такой приём часто встречается в типовом коде и работает быстрее вызова функции, что заметно в массовых обработках:

ДатаЧерез3Дня = ДатаНачала + 3 * 86400;        // +3 дня

ДатаЧерезПолтораЧаса = ДатаНачала + 90 * 60; // +90 минут

НачалоСледующегоДня = НачалоДня(ДатаНачала) + 86400;

Граница применимости: секунды, минуты, часы, дни, недели (7 × 86400). Всё, что длиннее недели, — только через ДобавитьКДате(), потому что длительность месяца и года непостоянна. Нарушение этого правила — одна из самых коварных ошибок: код Дата + 30 * 86400 вместо «плюс один месяц» большую часть времени работает «почти правильно», но на длинных и коротких месяцах даёт смещение на 1–3 дня, которое обнаруживается только при сверке документов.

Для получения разности дат (обратная операция) используется функция РазностьДат(Дата1, Дата2, ТипЧисла), которая возвращает количество единиц между двумя датами, либо простое вычитание Дата2 - Дата1, дающее разницу в секундах.

Сложение рабочих дней по производственному календарю

Стандартные функции оперируют календарными днями, но в учётных задачах часто требуется прибавить именно рабочие дни: срок доставки «5 рабочих дней», дата платежа «не позднее 3 банковских дней». Здесь простая арифметика не подходит — нужен производственный календарь.

В типовых конфигурациях (БСП) для этого существует регистр сведений «Данные производственного календаря» и программный интерфейс общего модуля КалендарныеГрафики. Типовой подход — запросом выбрать даты, следующие за исходной, с признаком рабочего дня, и взять N-ю по счёту:

ВЫБРАТЬ ПЕРВЫЕ 5

Данные.Дата КАК Дата

ИЗ

РегистрСведений.ДанныеПроизводственногоКалендаря КАК Данные

ГДЕ

Данные.ПроизводственныйКалендарь = &Календарь

И Данные.Дата > &ДатаНачала

И Данные.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)

УПОРЯДОЧИТЬ ПО

Данные.Дата

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

Проверка результата и контрольные точки

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

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

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

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

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

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

Получено 2–3 марта — использовано сложение через секунды

Прибавление дней к дате с временем 15:30
Норма

Время в результате сохранилось 15:30

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

Время сбросилось — где-то применено НачалоДня()

Расчёт на пустой дате 01.01.0001
Норма

Код явно проверяет ЗначениеЗаполнено(Дата)

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

Результат — дата января 0001 года без предупреждения

Рабочие дни через календарь
Норма

Срок не попадает на выходные и праздники

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

Результат пуст или равен исходной дате — календарь не заполнен

Отдельно проверьте поведение при пустой исходной дате. Пустая дата в 1С — это 01.01.0001, и ДобавитьКДате('00010101', "День", 14) честно вернёт 15.01.0001, не выдав ошибки. В прикладной логике такой результат почти всегда означает незаполненный реквизит, поэтому перед расчётом добавляйте проверку Если Не ЗначениеЗаполнено(ДатаДокумента) Тогда ....

Типичные ошибки при сложении дат

Типичные ошибки
01
Сложение Дата + N без перевода в секунды — дата сдвигается на N секунд вместо N дней
02
Месяцы через 30 * 86400 — накопление погрешности до 3 дней на длинных и коротких месяцах
03
Вызов функции без присваивания: ДобавитьКДате(Дата, "День", 5) — исходная переменная не меняется
04
Игнорирование состава даты: к дате с временем прибавляют дни, а потом удивляются, что документ не попадает в отчёт за день из-за времени 23:59
05
Расчёт рабочих дней вычитанием выходных «вручную» без учёта праздников и переносов
06
Отсутствие проверки пустой даты — в результате даты января 0001 года в печатных формах

Ещё одна группа ошибок связана с часовыми поясами. Функция ТекущаяДата() возвращает дату сеанса, которая может отличаться от даты сервера и от даты клиентского компьютера. Если сложение дат выполняется на сервере, а сравнивается с датой, введённой пользователем в другом часовом поясе, возможен сдвиг на сутки. В распределённых системах используйте ТекущаяДатаСеанса() и единообразный подход во всех расчётах.

Выбор способа под конкретную задачу

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

Как выбрать способ

Нужно прибавить дни, часы, минуты или секундыИспользуйте ДобавитьКДате() или сложение с переводом в секунды (N * 86400 для дней)
Нужно прибавить месяцы, кварталы или годыТолько ДобавитьМесяц() или ДобавитьКДате() с типом Месяц/Квартал/Год — никогда через секунды
Нужны рабочие дни с учётом праздниковЗапрос к данным производственного календаря, предварительно проверьте его заполнение
Нужно найти разницу между датамиРазностьДат() для единиц измерения или вычитание для секунд
Дата может быть пустойСначала проверка ЗначениеЗаполнено(), расчёт только при заполненном значении

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

Итог

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

Сложение дат в 1С выполняется через ДобавитьКДате() и ДобавитьМесяц(); прямое сложение прибавляет секунды. Месяцы и годы — только специальными функциями. Рабочие дни считаются по производственному календарю. Всегда проверяйте пустые даты и результат на границах месяца.

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

Как прибавить к дате 7 дней в 1С?

Два равнозначных способа: ДобавитьКДате(Дата, "День", 7) или Дата + 7 * 86400. Первый читаемее, второй чуть быстрее в циклах. Результат нужно присвоить переменной — исходная дата сама не изменится.

Почему Дата + 1 не прибавляет один день?

Потому что при арифметических операциях с типом «Дата» число интерпретируется как секунды. Дата + 1 сдвигает значение на одну секунду. Для дня нужно прибавить 86400 или использовать ДобавитьКДате().

Как вычесть из даты месяц?

Вызовите функцию с отрицательным параметром: ДобавитьМесяц(Дата, -1) или ДобавитьКДате(Дата, "Месяц", -1). Учтите, что от 31 марта вы получите последний день февраля — платформа подставляет конец месяца, если исходного числа в нём нет.

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

Стандартными функциями — никак. Нужен заполненный производственный календарь: запросом выбираются рабочие дни после исходной даты, и берётся N-я по счёту дата. В типовых конфигурациях используется регистр «Данные производственного календаря» и механизмы БСП.

Что будет, если прибавить дни к пустой дате?

Ошибки не будет: пустая дата — это 01.01.0001, и функция вернёт соответствующую дату января 0001 года. Такой результат в документах и отчётах выглядит как сбой, поэтому перед расчётом проверяйте дату через ЗначениеЗаполнено().

Можно ли складывать даты прямо в запросе?

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