Разработка и Конфигурация · 9 мин
Как в 1С добавить к дате день
Как в 1С добавить к дате день: функция ДобавитьКДате, прибавление секунд, работа с запросами. Примеры кода, типичные ошибки и проверка результата.
Задача прибавить к дате один или несколько дней возникает постоянно: при расчёте сроков оплаты, дат отгрузки, окончания договоров, плановых дат в документах. Во встроенном языке 1С для этого есть штатный механизм, и у него есть важные особенности, о которых нужно знать, чтобы не получить ошибку или неверный результат.
Главное, что нужно понимать: дата в 1С — это не число, а отдельный тип данных, хранящий значение с точностью до секунды. Поэтому просто написать «Дата + 1» нельзя — платформа выдаст ошибку о несоответствии типов. Корректных способов два: функция ДобавитьКДате() и прибавление количества секунд.
Ниже разобраны оба подхода, работа с датами в запросах, обработка граничных случаев (конец месяца, високосный год) и типичные ошибки, которые допускают даже опытные разработчики.
Функция ДобавитьКДате — основной способ
Штатная функция встроенного языка ДобавитьКДате() принимает три параметра: исходную дату, тип интервала (строкой) и величину интервала (число). Для добавления одного дня вызов выглядит так:
НоваяДата = ДобавитьКДате(ИсходнаяДата, "ДЕНЬ", 1);
Функция возвращает новое значение типа «Дата», не изменяя исходную переменную. Это важно: если нужно сохранить результат, его обязательно присваивают переменной или реквизиту. Тип интервала можно указывать как на русском («ДЕНЬ»), так и на английском («DAY») — оба варианта допустимы независимо от варианта встроенного языка конфигурации.
Кроме дней поддерживаются интервалы СЕКУНДА, МИНУТА, ЧАС, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ПОЛУГОДИЕ и ГОД. Это позволяет одной функцией решать любые задачи смещения дат. Для вычитания передаётся отрицательное число: ДобавитьКДате(Дата, "ДЕНЬ", -1) вернёт вчерашнюю дату.
// Добавить один день
Завтра = ДобавитьКДате(ТекущаяДатаСеанса(), "ДЕНЬ", 1);
// Добавить 14 дней к дате документа
СрокОплаты = ДобавитьКДате(Объект.Дата, "ДЕНЬ", 14);
// Вычесть 3 дня
ДатаНапоминания = ДобавитьКДате(СрокОплаты, "ДЕНЬ", -3);Как ведёт себя функция на границах месяца и года
Главное преимущество ДобавитьКДате() — корректная календарная арифметика. Если к 31 января прибавить один день, результатом будет 1 февраля, а не «32 января». Переход через год обрабатывается так же: 31 декабря плюс один день даст 1 января следующего года.
Високосные годы учитываются автоматически: прибавление дня к 28 февраля високосного года даст 29 февраля, а невисокосного — 1 марта. Разработчику не нужно реализовывать эту логику вручную.
Составляющая времени при добавлении дней сохраняется. Если исходная дата содержала время 14:30:00, то и результат будет содержать 14:30:00. Если нужно получить начало или конец результирующего дня, применяйте функции НачалоДня() или КонецДня() к результату.
Альтернатива: прибавление секунд
Второй рабочий способ — прибавить к дате число, которое платформа интерпретирует как количество секунд. В сутках 86400 секунд, поэтому добавление дня выглядит так:
НоваяДата = ИсходнаяДата + 86400; // один день
НоваяДата = ИсходнаяДата + 7 * 86400; // неделя
Способ короче и выполняется чуть быстрее, поэтому его часто используют в циклах при обходе диапазона дат. Однако у него есть ограничения: он не подходит для месяцев и лет (их длительность в секундах непостоянна), а код становится менее читаемым — по числу 86400 не всегда очевидно намерение автора.
Хорошая практика — выносить длительность суток в именованную переменную или константу модуля, например СекундВДне = 86400;. Это снимает вопросы при код-ревью и снижает риск опечатки в количестве нулей.
Сравнение вариантов
Универсально: дни, месяцы, годы. Корректные календарные переходы. Читаемый код. Чуть медленнее в массовых циклах.
Подходит только для дней и меньших интервалов. Быстро и компактно, удобно в циклах по диапазону дат. Не работает для месяцев и лет.
Единственный вариант, когда смещение нужно прямо в запросе — например, для сравнения сроков в выборке без постобработки.
Добавление дня к дате в запросе
В языке запросов 1С есть одноимённая функция ДОБАВИТЬКДАТЕ() с теми же параметрами. Она нужна, когда смещение даты требуется прямо в выборке — например, отобрать документы, у которых срок оплаты (дата плюс 10 дней) уже наступил:
ВЫБРАТЬ
Реализация.Ссылка,
ДОБАВИТЬКДАТЕ(Реализация.Дата, ДЕНЬ, 10) КАК СрокОплаты
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
ДОБАВИТЬКДАТЕ(Реализация.Дата, ДЕНЬ, 10) <= &ТекущаяДата
Обратите внимание: в запросе тип интервала указывается без кавычек — ДЕНЬ, МЕСЯЦ, ГОД и так далее. Это частая ошибка при переносе логики из кода в запрос. Прибавление секунд арифметикой в запросе не поддерживается — только функция.
Если смещение нужно только для сравнения, иногда проще и быстрее инвертировать условие: вместо добавления дней к дате документа вычесть их из текущей даты параметра. Это позволяет платформе эффективнее использовать индексы по полю даты.
Практические сценарии
Расчёт срока оплаты в документе
Типовая задача — при записи документа автоматически рассчитать дату оплаты как дату документа плюс отсрочка из договора. В модуле объекта это выглядит так:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЗначениеЗаполнено(Договор) Тогда
СрокОплаты = ДобавитьКДате(Дата, "ДЕНЬ", Договор.ОтсрочкаПлатежаДней);
КонецЕсли;
КонецПроцедуры
Перед использованием реквизита договора убедитесь, что он заполнен и имеет числовой тип — иначе при пустом значении получите дату документа без смещения или ошибку приведения типа.
Цикл по диапазону дат
Когда нужно обработать каждый день периода — например, сформировать табель или проверить остатки на каждую дату — удобен цикл с прибавлением секунд:
ТекДата = НачалоДня(НачалоПериода);
Пока ТекДата <= КонецДня(КонецПериода) Цикл
// обработка даты ТекДата
ТекДата = ТекДата + 86400;
КонецЦикла;
Обязательно задавайте начальное значение через НачалоДня(), иначе при диапазоне с ненулевым временем последний день может «выпасть» из цикла.
Дата на форме и в реквизитах
При работе на управляемой форме смещение даты выполняется в серверной или клиентской процедуре так же — ДобавитьКДате() доступна и на клиенте. Если дата редактируется пользователем, а зависимое поле должно пересчитываться, разместите расчёт в обработчике ПриИзменении поля ввода.
- 1Определите, где нужен расчёт: в коде модуля или в запросе
- 2Для кода используйте ДобавитьКДате(Дата, "ДЕНЬ", 1), для запроса — ДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, 1)
- 3Присвойте результат переменной или реквизиту — исходное значение не изменится
- 4При необходимости нормализуйте время через НачалоДня() или КонецДня()
- 5Проверьте результат на граничных датах: конец месяца, конец года, 28 февраля
Проверка результата и отладка
Простейший способ проверить расчёт — вывести значения через Сообщить() или посмотреть их в отладчике. Убедитесь, что и исходная, и результирующая даты имеют ожидаемый тип и составляющую времени.
Для проверки граничных случаев полезно прогнать расчёт на контрольном наборе: 31 января, 28 февраля, 31 декабря. Если во всех случаях результат соответствует календарю — реализация корректна.
Как проверить результат
Результат 01.02 того же года
Ошибка или дата вне календаря
Время результата совпадает с исходным или обнулено намеренно
Неожиданные 00:00:00, ломающие сравнения
Тип «Дата»
Число или строка — значит, где-то выполнено неверное преобразование
FAQ
Как вычесть день из даты в 1С?
Используйте ту же функцию с отрицательным параметром: ДобавитьКДате(Дата, "ДЕНЬ", -1). Либо вычтите секунды: Дата - 86400. Оба способа корректно обрабатывают переход на предыдущий месяц.
Можно ли прибавить к дате только рабочие дни?
Штатной функции для рабочих дней нет. Нужно использовать регистр сведений с производственным календарём (в типовых конфигурациях — «РегламентированныйПроизводственныйКалендарь») и в цикле отсчитывать только рабочие дни по данным календаря.
Почему ДобавитьКДате не меняет мою переменную?
Функция возвращает новое значение и не модифицирует аргумент. Результат нужно присвоить: Дата = ДобавитьКДате(Дата, "ДЕНЬ", 1).
Как добавить день к дате в запросе, если смещение хранится в реквизите?
Передайте реквизит третьим параметром: ДОБАВИТЬКДАТЕ(Документ.Дата, ДЕНЬ, Документ.ОтсрочкаДней). Третий параметр может быть полем или параметром запроса, не обязательно литералом.
Что произойдёт при добавлении дня к пустой дате?
Пустая дата в 1С — это 01.01.0001 00:00:00. Добавление дня даст 02.01.0001, что почти наверняка не то, что нужно. Перед расчётом проверяйте заполненность через ЗначениеЗаполнено(Дата).
Чем отличается ТекущаяДата() от ТекущаяДатаСеанса() при таких расчётах?
ТекущаяДатаСеанса() учитывает часовой пояс сеанса и корректнее для серверной логики в распределённых системах. Для расчёта сроков в документах рекомендуется именно она, чтобы даты не «съезжали» у пользователей в других часовых поясах.
Что важно запомнить
Для добавления дня к дате используйте ДобавитьКДате(Дата, "ДЕНЬ", 1) в коде и ДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, 1) в запросах. Функция возвращает новое значение и корректно обрабатывает календарные переходы. Прибавление 86400 секунд — допустимая альтернатива для дней в циклах. Всегда проверяйте заполненность исходной даты и составляющую времени.