Прибавление месяца к дате: функции и код в 1С
Содержание
Чтобы прибавить к дате ровно один календарный месяц, в 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
+ (Месяц(ДатаОкончания) - Месяц(ДатаНачала));
Возврат Месяцев;
КонецФункции
Здесь Год() и Месяц() выделяют из даты год и номер месяца. Формула переводит годы в месяцы и складывает с разницей номеров месяцев — удобно, когда день значения не имеет.
Какой способ выбрать — зависит от того, где вы считаете.
ДобавлениеМесяца(Дата, Число). Для первого/последнего числа оберните в НачалоМесяца или КонецМесяца.ДОБАВИТЬКДАТЕ(Дата, МЕСЯЦ, Число). Для разницы в месяцах — РАЗНОСТЬДАТ(..., МЕСЯЦ).86400 — получите число дней.Дата + 86400 * ЧислоДней. Для месяцев так делать нельзя.Частые ошибки при работе с датами
Несколько промахов, которые регулярно встречаются в коде новичков:
- ❌ «Прибавляют 30 дней вместо месяца». Запись
Дата + 86400 * 30даёт ровно 30 суток, а не календарный месяц. В январе-марте ошибётесь на 1–2 дня. - ❌ Путают
ТекущаяДата()иТекущаяДатаСеанса(). Первая работает на сервере, вторая — на клиенте. Вызов не той функции в своём контексте приведёт к ошибке компиляции. - ❌ Ждут 31-е число после прибавления месяца к
31 января. Его там быть не может — функция корректно вернёт конец февраля, и это не баг. - ❌ В запросе пишут вид интервала в кавычках (
"МЕСЯЦ"). Виды вДОБАВИТЬКДАТЕуказываются без кавычек, как ключевое слово.
Проверьте себя
Частые вопросы
Как называется функция для прибавления месяца в 1С?
ДобавлениеМесяца(Дата, ЧислоМесяцев). В запросах — ДОБАВИТЬКДАТЕ(Дата, МЕСЯЦ, Количество). Обе доступны на всех конфигурациях платформы 8.3.Можно ли прибавить к дате сразу несколько месяцев?
ДобавлениеМесяца указывают любое целое число, например ДобавлениеМесяца(Дата, 6) — плюс полгода. Отрицательное число вычитает месяцы.Что вернёт функция, если в целевом месяце нет нужного числа?
ДобавлениеМесяца(31 января, 1) даст 28 или 29 февраля — в зависимости от того, високосный ли год.Как прибавить месяц с учётом времени в дате?
14:00:00, оно останется и после сдвига месяца — функция меняет только месяц и, при переходе через декабрь, год.Чем отличается прибавление месяца от прибавления 30 дней?
86400 * 30), всегда ровно 30 суток. Прибавление месяца сдвигает именно календарный месяц: его длина разная (28–31 день), и переход года считается автоматически.