Работа с датами в 1С:Предприятие — одна из самых востребованных задач как для бухгалтеров, так и для программистов. Часто требуется сдвинуть дату на определённое количество месяцев: для расчёта сроков оплаты, планирования графиков, формирования отчётности или автоматизации бизнес-процессов. Однако простое сложение чисел здесь не работает — нужно учитывать разную продолжительность месяцев, високосные годы и даже особенности григорианского календаря.
В этой статье мы разберём 5 проверенных способов добавить месяц к дате в 1С 8.3 и 1С 7.7, от базовых функций платформы до программного кода с обработкой крайних случаев. Вы узнаете, как избежать ошибок при работе с последним днём месяца, как корректно обрабатывать отрицательные значения и какие нюансы важно учитывать при работе с периодическими данными. Материал будет полезен как начинающим пользователям, так и опытным разработчикам, которые хотят оптимизировать свои решения.
1. Базовый метод: функция ДобавитьМесяц()
Самый простой и надёжный способ сдвинуть дату на заданное количество месяцев — использовать встроенную функцию ДобавитьМесяц(). Она автоматически учитывает разную длину месяцев и корректно обрабатывает переходы через годовые границы.
Синтаксис функции:
ДобавитьМесяц(НачальнаяДата, КоличествоМесяцев)
Примеры использования:
- 📅 Прибавить 1 месяц:
ДобавитьМесяц(ТекущаяДата(), 1)→ если сегодня 31 января, результат будет 28 февраля (или 29 в високосный год). - 🔙 Отнять 2 месяца:
ДобавитьМесяц(ДатаДокумента, -2)→ полезно для расчёта просроченных платежей. - 📆 Сдвинуть на 12 месяцев:
ДобавитьМесяц('2023-12-15', 12)→ вернёт2026-12-15.
Особенности работы функции:
- ⚠️ Если итоговая дата выходит за пределы месяца (например, 31 апреля), функция автоматически корректирует её до последнего дня (30 апреля).
- ✅ Поддерживает отрицательные значения для вычитания месяцев.
- 🔄 Работает как в 1С 8.3, так и в 1С 7.7 (с небольшими синтаксическими различиями).
Если вам нужно сохранить последний день месяца при добавлении месяцев (например, 31.01 + 1 месяц = 28.02, но требуется 31.03), используйте комбинацию функций НачалоМесяца() и КонецМесяца().
2. Работа с датами через запросы 1С
В некоторых случаях удобнее добавлять месяцы непосредственно в тексте запроса, особенно если вы работаете с большими массивами данных в отчётах или обработках. Для этого в языке запросов 1С предусмотрен оператор ДОБАВИТЬ К ДАТЕ.
Пример запроса для сдвига даты на 3 месяца:
ВЫБРАТЬ
ДатаДокумента КАК ИсходнаяДата,
ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 3) КАК НоваяДата
ИЗ
Документ.РеализацияТоваровУслуг
Ключевые моменты:
- 📊 Оператор
ДОБАВИТЬ К ДАТЕподдерживает не только месяцы, но и дни, годы, часы. - 🔍 В результатах запроса можно сразу использовать рассчитанные даты для фильтрации или группировки.
- ⚡ Быстрее, чем программное добавление в цикле, при работе с тысячами записей.
Ограничения метода:
- ❌ Не позволяет гибко обрабатывать крайние случаи (например, всегда переходить на последний день месяца).
- 📉 В 1С 7.7 синтаксис запросов отличается — используйте функцию
ДобавитьМесяц()прямо в тексте запроса.
3. Программный код: гибкая обработка дат
Когда стандартных функций недостаточно (например, нужно учитывать рабочие/выходные дни или специфические бизнес-правила), приходится писать собственный код. Рассмотрим универсальную функцию, которая добавляет месяцы с учётом последнего дня:
Функция ДобавитьМесяцыСКоррекцией(НачальнаяДата, КоличествоМесяцев)
Если ТипЗнч(НачальнаяДата) <> Тип("Дата") Тогда
Возврат Неопределено;
КонецЕсли;
// Сохраняем день месяца
ДеньМесяца = День(НачальнаяДата);
// Получаем первый день месяца
ДатаНачало = НачалоМесяца(НачальнаяДата);
// Добавляем месяцы
НоваяДата = ДобавитьМесяц(ДатаНачало, КоличествоМесяцев);
// Пытаемся вернуть исходный день
Попытка
Результат = ДобавитьДень(НоваяДата, ДеньМесяца - 1);
Исключение
// Если день выходит за пределы месяца, берём последний день
Результат = КонецМесяца(НоваяДата);
КонецПопытки;
Возврат Результат;
КонецФункции
Преимущества этого подхода:
- 🎯 Точно сохраняет день месяца, если он существует в целевом месяце (например, 30.01 + 1 месяц = 30.02, а не 28.02).
- 🛡️ Корректно обрабатывает переходы через годовые границы.
- 🔧 Легко модифицировать под специфические требования (например, пропускать выходные).
Как модифицировать функцию для рабочих дней?
Добавьте проверку через функцию ЭтоРабочийДень() в цикле, пока не найдёте ближайший рабочий день после расчётной даты.
Пример использования:
Сообщить(ДобавитьМесяцыСКоррекцией('2023-01-31', 1)); // Вернёт 28.02.2023 (или 29.02 в високосный год)
Сообщить(ДобавитьМесяцыСКоррекцией('2023-01-30', 1)); // Вернёт 30.02.2023 → автоматически скорректируется до 28.02
4. Обработка крайних случаев: последний день месяца
Одна из самых распространённых проблем при работе с датами — корректная обработка последнего дня месяца. Например, если к 31.01.2023 добавить 1 месяц, стандартная функция вернёт 28.02.2023, что не всегда устраивает бизнес-логику. Рассмотрим альтернативные подходы.
Способ 1: Всегда последний день месяца
Функция ДобавитьМесяцДоКонца(НачальнаяДата, КоличествоМесяцев)
Возврат КонецМесяца(ДобавитьМесяц(НачалоМесяца(НачальнаяДата), КоличествоМесяцев));
КонецФункции
Способ 2: Сохранить день, если он существует (уже реализовано в функции из предыдущего раздела).
Сравнение методов:
| Метод | Пример (31.01 + 1 месяц) | Пример (15.01 + 1 месяц) | Когда использовать |
|---|---|---|---|
ДобавитьМесяц() |
28.02 | 15.02 | Стандартные случаи, когда важен календарный сдвиг |
| С коррекцией (наш код) | 28.02 | 15.02 | Когда нужно сохранить день, если он существует |
КонецМесяца() |
28.02 | 28.02 | Когда всегда нужен последний день месяца |
Для бухгалтерских расчётов (например, сроки уплаты налогов) чаще всего требуется именно последний день месяца, даже если исходная дата была не последней.
5. Добавление месяцев в 1С 7.7: особенности
В 1С:Предприятие 7.7 подходы к работе с датами несколько отличаются от современной платформы. Здесь нет функции ДобавитьМесяц(), но есть альтернативные методы.
Способ 1: Через компоненты даты
Процедура ДобавитьМесяц77(ДатаНач, Месяцев)
Год = Год(ДатаНач);
Месяц = Месяц(ДатаНач) + Месяцев;
// Корректируем год и месяц
Пока Месяц > 12 Цикл
Месяц = Месяц - 12;
Год = Год + 1;
КонецЦикла;
Пока Месяц < 1 Цикл
Месяц = Месяц + 12;
Год = Год - 1;
КонецЦикла;
// Определяем последний день месяца
День = День(КонецМесяца(Дата(Год, Месяц, 1)));
ДатаРез = Дата(Год, Месяц, Миним(День(ДатаНач), День));
Возврат ДатаРез;
КонецПроцедуры
Способ 2: Через ОLE-объекты (если доступен)
В некоторых конфигурациях 1С 7.7 можно использовать VBScript через OLE:
OLE = СоздатьОбъект("ScriptControl");
OLE.Language = "VBScript";
ДатаРез = OLE.Eval("DateAdd(""m"", " + Месяцев + ", """ + Формат(ДатаНач, "ДЛФ=D") + """)");
Сделать резервную копию базы|Проверить совместимость с версией платформы|Тестировать на копии рабочей базы|Учесть особенности конфигурации-->
⚠️ Внимание: В 1С 7.7 отсутствует встроенная обработка високосных годов в функции КонецМесяца() для февраля. При работе с датами вручную всегда проверяйте результат для февраля 2020, 2026 и других високосных годов.
6. Практическое применение: примеры из бухгалтерии и кадров
Добавление месяцев к датам широко используется в типовых конфигурациях 1С. Рассмотрим реальные примеры:
1. Расчёт сроков уплаты налогов
В 1С:Бухгалтерия часто требуется определить последний день месяца, следующего за отчётным периодом. Например, для декларации по НДС за 1 квартал 2023 года срок уплаты — 25 апреля 2023 года, но если 25 число выпадает на выходной, срок переносится. Код для расчёта:
ДатаСдачи = КонецМесяца(ДобавитьМесяц(НачалоМесяца(ДатаОкончанияКвартала), 1));
Если Не ЭтоРабочийДень(ДатаСдачи) Тогда
ДатаСдачи = СледующийРабочийДень(ДатаСдачи);
КонецЕсли;
2. Графики отпусков в 1С:Зарплата и Управление Персоналом
При планировании отпусков нужно учитывать, что дата окончания отпуска должна быть рабочим днём. Пример кода для расчёта даты выхода:
ДатаНачалаОтпуска = '2023-06-01';
Длительность = 14; // дней
ДатаОкончания = ДобавитьДень(ДатаНачалаОтпуска, Длительность - 1);
Пока Не ЭтоРабочийДень(ДатаОкончания) Цикл
ДатаОкончания = ДобавитьДень(ДатаОкончания, 1);
КонецЦикла;
3. Планирование платежей по кредитам
В 1С:Управление торговлей или 1С:ERP часто требуется формировать график погашения кредита с ежемесячными платежами. Здесь важно, чтобы дата платежа не выпадала на выходной:
ДатаПервогоПлатежа = '2023-03-15';
КоличествоПлатежей = 12;
Для Сч = 1 По КоличествоПлатежей Цикл
ТекущаяДата = ДобавитьМесяц(ДатаПервогоПлатежа, Сч - 1);
Если Не ЭтоРабочийДень(ТекущаяДата) Тогда
ТекущаяДата = ПредыдущийРабочийДень(ТекущаяДата);
КонецЕсли;
ГрафикПлатежей.Добавить(ТекущаяДата);
КонецЦикла;
Для проверки рабочих дней в 1С используйте функцию ЭтоРабочийДень() из стандартных библиотек или создайте собственную с учётом производственного календаря.
7. Частые ошибки и как их избежать
При работе с датами в 1С даже опытные разработчики допускают ошибки. Разберём типичные проблемы и способы их решения.
Ошибка 1: Игнорирование високосных годов
Если вы вручную рассчитываете даты, не поленитесь проверить обработку февраля. Например, этот код ошибочно вернёт 28.02.2020 вместо 29.02.2020:
// НЕПРАВИЛЬНО!
НоваяДата = Дата(2020, 2, 28);
Решение: всегда используйте КонецМесяца() или встроенные функции.
Ошибка 2: Неучёт временных зон
В распределённых системах (например, при обмене данными между филиалами) даты могут интерпретироваться по-разному. Всегда явным образом указывайте временную зону:
ТекущаяДата = ТекущаяДатаСеанса(); // Берёт дату с учётом временной зоны пользователя
Ошибка 3: Прямое сложение чисел
Никогда не прибавляйте месяцы как числа к компонентам даты:
// НЕПРАВИЛЬНО!
НовыйМесяц = Месяц(ТекущаяДата) + 1; // Ошибка, если ТекущаяДата = декабрь!
Ошибка 4: Забывают про null-значения
Всегда проверяйте входные параметры на Неопределено или пустые даты:
Если ДатаДокумента = '00010101' Или Не ЗначениеЗаполнено(ДатаДокумента) Тогда
Возврат Неопределено;
КонецЕсли;
⚠️ Внимание: В 1С 8.3 пустая дата может быть представлена как'0001-01-01'илиНеопределено. Всегда проверяйте оба варианта, если работаете с пользовательским вводом.
FAQ: Ответы на частые вопросы
Как добавить месяц к дате в отчёте 1С без программирования?
В большинстве стандартных отчётов (например, в 1С:Бухгалтерия) можно использовать пользовательские поля с формулами. Добавьте новое поле и введите выражение:
ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 1)
Если отчёт не поддерживает такие формулы, создайте внешнюю обработку или модифицируйте отчёт в конфигураторе.
Почему функция ДобавитьМесяц() возвращает неверную дату для 31 числа?
Это не ошибка, а особенность работы функции. Она сохраняет порядковый номер дня в месяце. Например, 31 января — это 31-й день месяца, а в феврале максимум 28(29) дней. Поэтому функция возвращает последний день февраля.
Если вам нужно, чтобы 31.01 + 1 месяц = 31.03, используйте метод с коррекцией из раздела 4.
Как добавить месяц к дате в мобильном приложении 1С?
В мобильной платформе 1С:Предприятие доступны те же функции, что и в десктопной версии. Используйте:
НоваяДата = ДобавитьМесяц(ТекущаяДата(), 1);
Ограничения:
- ⚠️ Некоторые сложные операции (например, работа с OLE) недоступны.
- 📱 Производительность мобильных устройств ниже — избегайте тяжелых циклов.
Можно ли добавить месяц к дате в 1С:УТ 10.3?
Да, в 1С:Управление торговлей 10.3 (как и в других конфигурациях на платформе 8.2/8.3) доступна функция ДобавитьМесяц(). Пример для расчёта даты отгрузки:
ДатаОтгрузки = ДобавитьМесяц(ДатаЗаказа, 1);
Если ДеньНедели(ДатаОтгрузки) = 6 Тогда // Если суббота
ДатаОтгрузки = ДобавитьДень(ДатаОтгрузки, 2); // Переносим на понедельник
КонецЕсли;
Как добавить месяц к дате в запросе с группировкой?
Используйте оператор ДОБАВИТЬ К ДАТЕ прямо в разделе ГДЕ или ВЫБРАТЬ. Пример запроса для группировки документов по месяцам с учётом сдвига:
ВЫБРАТЬ
ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 1) КАК МесяцОтгрузки,
СУММА(СуммаДокумента) КАК Итого
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
ДОБАВИТЬ К ДАТЕ(ДатаДокумента, МЕСЯЦ, 1)