Прибавление месяца к дате: функции и код в 1С

· 8 мин

Содержание

Чтобы прибавить к дате ровно один календарный месяц, в 1С 8.3 используют встроенную функцию ДобавлениеМесяца(Дата, ЧислоМесяцев). Складывать дату с числом секунд для этого нельзя: в месяцах разное количество дней, и такой расчёт собьётся. А в запросах ту же задачу решает функция ДОБАВИТЬКДАТЕ с видом МЕСЯЦ.

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

Тип «Дата» и как он хранится

В платформе 1С тип Дата всегда хранит и дату, и время одновременно. Даже если вы задали только день, внутри лежит момент времени — по умолчанию 00:00:00.

Создать дату в коде можно литералом в одинарных кавычках или функцией Дата:

ДеньРождения = '20240131'; // 31 января 2024, время 00:00:00
ДеньРождения = '20240131120000'; // то же число, время 12:00:00
ДеньРождения = Дата(2024, 1, 31); // через функцию: год, месяц, день

Физически значение типа Дата — это количество секунд, отсчитанное от условной точки. Отсюда простое правило:

  • 💡 прибавить к дате число — значит прибавить столько секунд;
  • 86400 секунд = одни сутки;
  • 3600 — один час, 60 — минута.

Поэтому выражение ДеньРождения + 86400 даёт следующий день. А вот «плюс месяц» через сложение с числом так просто не записать — месяц не равен фиксированному числу секунд.

Текущую дату в серверном коде берут функцией ТекущаяДата(), а в клиентском — ТекущаяДатаСеанса(). Это разные функции, и на клиенте ТекущаяДата() недоступна.

Функция ДобавлениеМесяца — главный инструмент

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

Результат = ДобавлениеМесяца(ИсходнаяДата, ЧислоМесяцев);

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

ДатаДокумента = Дата(2024, 3, 15);

ЧерезМесяц   = ДобавлениеМесяца(ДатаДокумента, 1);  // 15.04.2024
ЧерезПолгода = ДобавлениеМесяца(ДатаДокумента, 6);  // 15.09.2024
МесяцНазад   = ДобавлениеМесяца(ДатаДокумента, -1); // 15.02.2024

Время внутри даты функция сохраняет. Если в исходном значении было 12:30:00, оно останется и в результате — меняется только месяц (и при необходимости год).

Когда счётчик месяцев переваливает за декабрь, год увеличивается автоматически:

Декабрь = Дата(2024, 12, 10);
Январь  = ДобавлениеМесяца(Декабрь, 1); // 10.01.2025 — год стал 2025

Не пытайтесь заменить ДобавлениеМесяца сложением даты с числом вроде + 2592000 (30 суток). Такой «месяц» будет то длиннее, то короче реального, и в учётных расчётах даст расхождение в днях.

Арифметика дат: что считать секундами, а что — функцией

Сложение и вычитание с типом Дата работает в секундах. Это удобно для коротких интервалов и для разницы между датами.

ЗадачаКак записатьРезультат
Прибавить деньДата + 86400следующие сутки
Прибавить неделюДата + 86400 * 7+7 дней
Разница в днях(Дата2 - Дата1) / 86400число дней
Прибавить месяцДобавлениеМесяца(Дата, 1)+1 календарный месяц

Вычитание двух дат возвращает число секунд между ними. Чтобы получить дни, делят на 86400:

ДнейМеждуДатами = (Дата(2024, 3, 1) - Дата(2024, 2, 1)) / 86400; // 29 (февраль 2024 — високосный)

Обратите внимание на последнюю строку: ответ получился 29, а не 30. Февраль 2024 года длиннее на день. Это и есть причина, по которой месяц нельзя считать фиксированным числом секунд.

Для начала и конца месяца есть отдельные функции — их часто комбинируют с ДобавлениеМесяца:

// Первое число следующего месяца
НачалоСледующего = НачалоМесяца(ДобавлениеМесяца(ТекущаяДата(), 1));

// Последний момент текущего месяца (23:59:59)
ПоследнийМомент = КонецМесяца(ТекущаяДата());

НачалоМесяца сбрасывает день на первое число и время на 00:00:00. КонецМесяца ставит последний день месяца и время 23:59:59.

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

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

ВЫБРАТЬ
    РеализацияТоваровУслуг.Дата КАК ДатаОтгрузки,
    ДОБАВИТЬКДАТЕ(РеализацияТоваровУслуг.Дата, МЕСЯЦ, 1) КАК СрокОплаты
ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

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

Разницу между датами в запросе считает парная функция РАЗНОСТЬДАТ:

ВЫБРАТЬ
    РАЗНОСТЬДАТ(Договор.Дата, &ТекущаяДата, МЕСЯЦ) КАК МесяцевПрошло
ИЗ
    Справочник.Договоры КАК Договор

РАЗНОСТЬДАТ(..., МЕСЯЦ) считает именно границы месяцев, а не полные 30-дневные промежутки. Между 31.01 и 01.02 она вернёт 1, хотя прошли всего сутки.

Это важное отличие от расчёта в днях: если вам нужна разница именно в календарных месяцах для начисления аренды, процентов или рассрочки — берите РАЗНОСТЬДАТ с видом МЕСЯЦ, а не делите секунды.

Конец месяца и високосные годы

Главная ловушка — что делать, когда в целевом месяце нет такого же числа. Например, прибавляем месяц к 31 января. В феврале нет 31-го числа.

Функция ДобавлениеМесяца решает это однозначно: если в новом месяце нужного дня нет, результатом будет последний день этого месяца.

// 2024 год — високосный, в феврале 29 дней
ДобавлениеМесяца(Дата(2024, 1, 31), 1); // 29.02.2024

// 2023 год — обычный, в феврале 28 дней
ДобавлениеМесяца(Дата(2023, 1, 31), 1); // 28.02.2023

// 30 января тоже «упрётся» в конец февраля
ДобавлениеМесяца(Дата(2023, 1, 30), 1); // 28.02.2023

То есть и 30, и 31 января после прибавления месяца дадут одинаковый результат — последний день февраля. Високосность функция учитывает сама, вручную её проверять не нужно.

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

ПервоеЧислоСледующего = НачалоМесяца(ДобавлениеМесяца(ИсходнаяДата, 1));

А если задача — получить именно последний день через N месяцев (типичный случай для сроков договоров), помогает КонецМесяца:

КонецЧерезКвартал = КонецМесяца(ДобавлениеМесяца(ТекущаяДата(), 3));

Отдельный случай — 29 февраля високосного года. При сдвиге на год такого числа в обычном году не окажется, и функция снова возьмёт конец месяца:

ДобавлениеМесяца(Дата(2024, 2, 29), 12); // 28.02.2025 — в 2025-м нет 29 февраля

Поэтому если вы считаете «ровно через год» от 29 февраля, будьте готовы, что три года подряд результат будет 28-м числом и только на четвёртый вернётся 29-е.

Проверить год на високосность в коде отдельной функции нет, но это несложно — через длину февраля:

Функция ГодВисокосный(Год)
    ПервоеФевраля = Дата(Год, 2, 1);
    ДнейВФеврале = День(КонецМесяца(ПервоеФевраля));
    Возврат ДнейВФеврале = 29;
КонецФункции

Здесь День() возвращает номер дня из даты, а КонецМесяца даёт 28 или 29 февраля — по нему и определяем високосный год.

Готовые примеры для типовых задач

Ниже — фрагменты, которые чаще всего нужны на практике. Их можно вставить в модуль и адаптировать.

Срок оплаты «плюс месяц» от даты отгрузки:

Функция СрокОплаты(ДатаОтгрузки, МесяцевОтсрочки = 1)
    Возврат ДобавлениеМесяца(ДатаОтгрузки, МесяцевОтсрочки);
КонецФункции

Период следующего месяца от текущей даты (для отбора):

НачалоПериода = НачалоМесяца(ДобавлениеМесяца(ТекущаяДатаСеанса(), 1));
КонецПериода  = КонецМесяца(НачалоПериода);

Список из 12 дат — по первому числу каждого месяца на год вперёд:

Даты = Новый Массив;
Старт = НачалоМесяца(ТекущаяДата());
Для Смещение = 0 По 11 Цикл
    Даты.Добавить(ДобавлениеМесяца(Старт, Смещение));
КонецЦикла;

Сколько полных месяцев прошло между двумя датами (в коде, без запроса):

Функция МесяцевМежду(ДатаНачала, ДатаОкончания)
    Месяцев = (Год(ДатаОкончания) - Год(ДатаНачала)) * 12
            + (Месяц(ДатаОкончания) - Месяц(ДатаНачала));
    Возврат Месяцев;
КонецФункции

Здесь Год() и Месяц() выделяют из даты год и номер месяца. Формула переводит годы в месяцы и складывает с разницей номеров месяцев — удобно, когда день значения не имеет.

Какой способ выбрать — зависит от того, где вы считаете.

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

Частые ошибки при работе с датами

Несколько промахов, которые регулярно встречаются в коде новичков:

  • ❌ «Прибавляют 30 дней вместо месяца». Запись Дата + 86400 * 30 даёт ровно 30 суток, а не календарный месяц. В январе-марте ошибётесь на 1–2 дня.
  • ❌ Путают ТекущаяДата() и ТекущаяДатаСеанса(). Первая работает на сервере, вторая — на клиенте. Вызов не той функции в своём контексте приведёт к ошибке компиляции.
  • ❌ Ждут 31-е число после прибавления месяца к 31 января. Его там быть не может — функция корректно вернёт конец февраля, и это не баг.
  • ❌ В запросе пишут вид интервала в кавычках ("МЕСЯЦ"). Виды в ДОБАВИТЬКДАТЕ указываются без кавычек, как ключевое слово.

Проверьте себя

Проверьте себя
Чему равен результат `ДобавлениеМесяца(Дата(2023, 1, 31), 1)`?
Как правильно прибавить ровно одни сутки к значению типа «Дата»?
Какой функцией сдвинуть дату на месяц в тексте запроса?

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

Как называется функция для прибавления месяца в 1С?
В коде — ДобавлениеМесяца(Дата, ЧислоМесяцев). В запросах — ДОБАВИТЬКДАТЕ(Дата, МЕСЯЦ, Количество). Обе доступны на всех конфигурациях платформы 8.3.
Можно ли прибавить к дате сразу несколько месяцев?
Да. Во втором параметре ДобавлениеМесяца указывают любое целое число, например ДобавлениеМесяца(Дата, 6) — плюс полгода. Отрицательное число вычитает месяцы.
Что вернёт функция, если в целевом месяце нет нужного числа?
Последний день этого месяца. ДобавлениеМесяца(31 января, 1) даст 28 или 29 февраля — в зависимости от того, високосный ли год.
Как прибавить месяц с учётом времени в дате?
Время сохраняется автоматически. Если в исходной дате было 14:00:00, оно останется и после сдвига месяца — функция меняет только месяц и, при переходе через декабрь, год.
Чем отличается прибавление месяца от прибавления 30 дней?
Прибавление 30 дней — это сложение с числом секунд (86400 * 30), всегда ровно 30 суток. Прибавление месяца сдвигает именно календарный месяц: его длина разная (28–31 день), и переход года считается автоматически.