Разработка и Конфигурация · 9 мин
Как в 1С получить количество месяцев между датами
Как в 1С посчитать количество месяцев между двумя датами: разность через функцию РазностьДат, запросы, типовые механизмы ЗУП и УТ. Примеры кода, ошибки и FAQ.
Задача посчитать количество месяцев между двумя датами встречается в 1С постоянно: расчёт стажа, длительности договоров, сроков гарантии, периодов обслуживания, возраста сотрудника. Встроенного оператора «вычесть месяцы» во встроенном языке нет, поэтому разработчики используют несколько рабочих приёмов — от функции РазностьДат до арифметики с годами и месяцами.
Выбор способа зависит от контекста: где выполняется расчёт (на клиенте, на сервере, в запросе), нужно ли учитывать неполные месяцы и как трактовать «разницу в месяцах» — как целое число полностью прошедших месяцев или как календарную разницу. Ниже разобраны основные методы с примерами кода, их ограничения и типичные ошибки.
Что считать «количеством месяцев между датами»
Прежде чем писать код, нужно определиться с бизнес-логикой. Между 15 января и 14 марта — один полный месяц или два? Между 31 января и 1 марта — один месяц или два? От ответа зависит формула.
Обычно выделяют три трактовки:
- Полные месяцы — месяц засчитывается, только если прошёл целиком (аналогично расчёту стажа). Между 15.01 и 14.03 — один полный месяц.
- Календарная разность — разница номеров месяцев без учёта дней. Между 31.01 и 01.03 — два месяца, хотя прошло чуть больше месяца.
- Округлённая разность — считаются дни, делятся на 30 или 30,44 и округляются. Подходит для приблизительных оценок, но даёт погрешность.
Для кадровых и договорных расчётов почти всегда нужны полные месяцы. Для аналитических отчётов допустима календарная разность. Уточните требование у постановщика задачи до написания кода — переделка логики после внедрения обходится дороже.
Функция РАЗНОСТЬДАТ в запросах 1С
Самый простой и надёжный способ — вычисление на уровне запроса. Язык запросов 1С поддерживает функцию РАЗНОСТЬДАТ, которая возвращает разницу в указанных единицах, в том числе в месяцах.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, МЕСЯЦ) КАК КоличествоМесяцев";
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
Результат = Запрос.Выполнить().Выгрузить();
Функция считает разницу в полных единицах: с 15.01 по 14.03 вернёт 1, с 15.01 по 15.03 — 2. Это именно поведение «полных месяцев», которое нужно в большинстве учётных задач.
Преимущества подхода: вычисление выполняется на СУБД, работает быстро даже на больших выборках, результат можно сразу использовать в группировках и условиях. Если нужно посчитать месяцы для тысячи строк таблицы — делайте это в запросе, а не в цикле.
Расчёт во встроенном языке без запроса
Формула через годы и месяцы
Когда запрос не нужен (например, расчёт в форме или при обработке одной строки), используйте арифметику:
// Календарная разность без учёта дней
КоличествоМесяцев = (Год(ДатаОкончания) - Год(ДатаНачала)) * 12
+ Месяц(ДатаОкончания) - Месяц(ДатаНачала);
// Поправка на неполный месяц
Если День(ДатаОкончания) < День(ДатаНачала) Тогда
КоличествоМесяцев = КоличествоМесяцев - 1;
КонецЕсли;
Первая часть даёт календарную разницу, поправка по дню переводит её в «полные месяцы». Проверьте граничные случаи: 31 января и 28 февраля — день окончания меньше дня начала, формула вычтет месяц, хотя февраль короче. Для строгих кадровых расчётов такие случаи обрабатывают отдельно.
Типовые функции общих модулей
В конфигурациях на Библиотеке стандартных подсистем (БП, УТ, ERP, ЗУП) есть готовые механизмы. Например, в ЗУП расчёт стажа реализован в модулях работы со стажами, а в БСП есть функции формирования представления периода. Перед написанием собственной функции поищите подходящую в общих модулях конфигурации через глобальный поиск по словам «РазностьДат», «Стаж», «Месяцев» — это избавит от дублирования и расхождений с типовой логикой.
КоличествоМесяцев = (Год(Дата2) - Год(Дата1)) * 12 + Месяц(Дата2) - Месяц(Дата1);Сравнение способов расчёта
| Способ | Где применять | Ограничения |
|---|---|---|
| РАЗНОСТЬДАТ в запросе | Отчёты, выборки, динамические списки | Только внутри запроса, недоступна в коде напрямую |
| Формула (Год*12 + Месяц) | Формы, обработки, серверные процедуры | Требует ручной поправки на дни |
| Типовые функции БСП/ЗУП | Стаж, кадровые расчёты | Зависимость от состава конфигурации |
| Разница в днях / 30 | Грубые прикидки | Погрешность, непригодна для учёта |
Для отчётов и массовых вычислений выбирайте РАЗНОСТЬДАТ. Для интерактивных форм — формулу в коде. Для стажа и кадровых документов — типовые механизмы конфигурации, чтобы не расходиться с расчётами зарплаты.
Граничные случаи и типичные ошибки
Больше всего проблем доставляют даты на стыке месяцев разной длины и незаполненные даты. Пустая дата в 1С — это 01.01.0001, и если она попадёт в расчёт, результатом будут тысячи месяцев или отрицательные значения.
Ещё одна ошибка — смешение трактовок в одном отчёте: одна колонка считает полные месяцы, другая календарные. Пользователи видят расхождения и теряют доверие к отчёту. Зафиксируйте единое правило в комментарии к коду и в описании отчёта.
Проверка корректности результата
Перед передачей доработки проверьте расчёт на контрольных примерах. Достаточно пяти-шести пар дат, покрывающих типовые и граничные ситуации.
Как проверить результат
Результат 2 месяца
1 или 3 — сбита трактовка полных месяцев
1 полный месяц
2 — не учтён день месяца
2 месяца
Отрицательное число — ошибка в формуле с годами
Расчёт пропущен, выведено 0 или сообщение
Тысячи месяцев или падение с ошибкой
Контролируемое сообщение или 0
Отрицательное значение уходит в итоги
Удобно оформить проверку как небольшую процедуру с циклом по таблице тестовых пар и сравнением с ожидаемым значением. При изменении формулы достаточно перезапустить проверку, а не вспоминать случаи вручную.
Порядок внедрения расчёта в конфигурацию
- 1Уточните у постановщика трактовку: полные месяцы или календарная разность
- 2Определите место расчёта: запрос для отчётов, код для форм и обработок
- 3Проверьте наличие типовой функции в общих модулях конфигурации
- 4Реализуйте расчёт с защитой от пустых дат и обратного порядка дат
- 5Прогоните контрольные примеры, включая границы года и 31 января
- 6Задокументируйте правило расчёта в комментарии и описании для пользователей
Если доработка затрагивает типовой документ, размещайте расчёт в расширении или в подписке на событие, а не правьте типовой модуль — иначе усложните обновление конфигурации.
Частые вопросы
Есть ли в 1С встроенная функция «МесяцыМеждуДатами»?
Отдельной функции во встроенном языке нет. В запросах используется РАЗНОСТЬДАТ с параметром МЕСЯЦ, в коде — формула через Год() и Месяц() или типовые функции общих модулей конкретной конфигурации.
Как посчитать месяцы с дробной частью?
Посчитайте полные месяцы, а остаток в днях разделите на количество дней в текущем месяце даты окончания. Получите значение вида 3,5 месяца. Точность будет условной, так как месяцы имеют разную длину.
Почему РАЗНОСТЬДАТ возвращает отрицательное число?
Дата начала больше даты окончания. Проверяйте порядок параметров перед вызовом или используйте конструкцию ВЫБОР в запросе, чтобы подставить 0 или поменять даты местами.
Как учесть, что февраль короче, при расчёте с 31 января?
Строгого общего правила нет — зависит от методики. Часто применяют вариант: если день начала больше числа дней в месяце окончания, месяц считается полным при достижении последнего дня месяца окончания. Согласуйте правило с постановщиком.
Можно ли посчитать месяцы в СКД без изменения запроса?
Да, через вычисляемое поле с выражением на языке выражений СКД, но функции разности дат там ограничены. Проще добавить РАЗНОСТЬДАТ прямо в набор данных — так расчёт выполнится на сервере БД.
Чем отличается расчёт стажа от простого числа месяцев?
Стаж обычно считают в годах, месяцах и днях с особыми правилами включения периодов и округления. Используйте типовые механизмы ЗУП или БСП, а не самописную формулу, чтобы результаты совпадали с кадровыми отчётами.
Что важно запомнить
В запросах используйте РАЗНОСТЬДАТ с параметром МЕСЯЦ, в коде — формулу (Год2-Год1)*12 + Месяц2 - Месяц1 с поправкой на день. Заранее договоритесь о трактовке «полного месяца», защититесь от пустых и перепутанных дат и проверьте расчёт на граничных примерах.