К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как в 1С посчитать количество месяцев между датами

Способы расчёта количества месяцев между датами в 1С: функции РазностьДат, ДобавитьМесяц, готовые процедуры БСП, примеры кода и типичные ошибки.

Задача посчитать количество месяцев между двумя датами возникает в 1С постоянно: при расчёте стажа сотрудника, срока действия договора, периода амортизации, длительности подписки или отсрочки платежа. При этом встроенного оператора «количество месяцев между датами» в языке 1С нет — результат получают комбинацией стандартных функций работы с датами.

Основная сложность в том, что «месяц» — нефиксированная величина: от 28 до 31 дня. Поэтому важно сразу определиться, что именно считается месяцем в вашей задаче: полный календарный месяц, разность номеров месяцев или период в 30 дней. От этого зависит выбор метода и корректность результата.

Ниже разобраны рабочие способы расчёта: через функцию РазностьДат в запросе, через ДобавитьМесяц в коде, через готовые процедуры библиотеки стандартных подсистем, а также типичные ошибки и способы проверки результата.

Что считать месяцем: три разные логики расчёта

Прежде чем писать код, определите бизнес-логику. Первый вариант — полные календарные месяцы: с 10 января по 9 февраля месяц ещё не прошёл, а с 10 февраля — прошёл. Именно так обычно считают стаж, сроки договоров и подписок.

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

Третий вариант — условный месяц фиксированной длины (30 дней или средняя продолжительность). Он встречается в финансовых расчётах, например при начислении неустойки, где договором закреплён «месяц = 30 дней». Смешивать эти подходы нельзя: одна и та же пара дат даст разные результаты.

Маршрут решения

Как выбрать способ расчёта

Нужен стаж, срок договора, возрастСчитайте полные календарные месяцы с поправкой на день месяца
Нужно сгруппировать данные по месяцам в отчётеИспользуйте РАЗНОСТЬДАТ с типом МЕСЯЦ в запросе
Договором зафиксирован месяц в 30 днейДелите разность дат в днях на 30 с округлением по правилам договора

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

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

ВЫБРАТЬ

РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, МЕСЯЦ) КАК КоличествоМесяцев

Важная особенность: РАЗНОСТЬДАТ считает количество пересечённых границ месяцев, а не полные месяцы в строгом смысле. Между 31 января и 1 февраля функция вернёт 1, хотя прошли сутки. Если нужны именно полные месяцы, добавьте проверку дня месяца через ДЕНЬ() и скорректируйте результат в выборке или после выполнения запроса.

Для отчётов на СКД функция работает так же — её можно использовать в вычисляемых полях и в выражениях ресурсов. Это самый быстрый способ получить количество месяцев сразу для большого массива строк без обхода выборки в коде.

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

Расчёт в коде модуля: формула с поправкой на день

Встроенной функции «месяцев между датами» во встроенном языке нет, поэтому используют формулу через год и месяц:

Функция МесяцевМеждуДатами(Дата1, Дата2) Экспорт

Если Дата1 > Дата2 Тогда

Возврат -МесяцевМеждуДатами(Дата2, Дата1);

КонецЕсли;

Результат = (Год(Дата2) - Год(Дата1)) * 12 + Месяц(Дата2) - Месяц(Дата1);

Если День(Дата2) < День(Дата1) Тогда

Результат = Результат - 1;

КонецЕсли;

Возврат Результат;

КонецФункции

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

Крайний случай — конец месяца. Между 31 января и 28 февраля формула выше вернёт 0, потому что 28-е меньше 31-го. Если по правилам учёта период с 31 января по 28 (29) февраля должен считаться полным месяцем, добавьте отдельную проверку: если Дата2 — последний день месяца и День(Дата1) больше День(Дата2), месяц считается полным.

Расчёт через ДобавитьМесяц и готовые функции БСП

Альтернативный способ — итеративный: прибавлять к начальной дате по месяцу функцией ДобавитьМесяц, пока результат не превысит конечную дату. Количество успешных итераций и есть число полных месяцев. Способ медленнее формулы, но нагляден и удобен, когда нужно заодно получить даты границ каждого месяца, например для помесячного графика платежей.

Если конфигурация построена на библиотеке стандартных подсистем (БСП), проверьте общий модуль работы с датами — там обычно есть готовые функции расчёта разности дат в разных единицах. В типовых конфигурациях (ЗУП, Бухгалтерия) есть свои процедуры расчёта стажа и периодов, которые уже учитывают принятые в учёте правила. Перед написанием своей функции поищите существующие через глобальный поиск по конфигурации — это сэкономит время и избавит от расхождений с типовой логикой.

Для разовых проверок без изменения конфигурации удобна консоль кода или обработка «выполнить произвольный код»: вставьте формулу из предыдущего раздела и подставьте нужные даты. Это безопасно, так как не меняет данные базы.

Порядок действий при самостоятельной реализации
  1. 1
    Определите, что считается месяцем: полный календарный, разность номеров или 30 дней
  2. 2
    Проверьте, есть ли готовая функция в общих модулях конфигурации
  3. 3
    Если нет — добавьте функцию с формулой через Год, Месяц и поправкой на день
  4. 4
    Протестируйте на граничных парах: 31.01–28.02, 15.03–14.04, 01.01–31.12
  5. 5
    Убедитесь, что результат совпадает с ожиданиями учётной политики

Проверка результата и граничные случаи

Любую функцию расчёта месяцев стоит прогнать на контрольном наборе дат. Между 15 января и 14 февраля полных месяцев ноль, между 15 января и 15 февраля — один. Между 1 января и 31 декабря одного года — 11 полных месяцев по формуле с поправкой, хотя интуитивно ожидают 12; если нужен «полный год», конечную дату берут как конец дня 31 декабря или прибавляют день.

Отдельно проверьте переход через год (ноябрь — февраль следующего года), високосный февраль и случай, когда даты совпадают — корректный результат ноль. Также убедитесь, что функция не падает на пустых датах: в 1С пустая дата — это 01.01.0001, и без проверки на Не ЗначениеЗаполнено(Дата) вы получите огромное число месяцев.

Контрольные точки

Как проверить результат

Пара 15.01–15.02
Норма

Функция возвращает 1

Тревожный признак

Возвращает 0 или 2

Пара 31.01–28.02
Норма

Результат соответствует принятому правилу (0 или 1) и задокументирован

Тревожный признак

Поведение случайное, никто не знает, почему так

Пустая дата на входе
Норма

Функция возвращает 0 или явно сигнализирует об ошибке

Тревожный признак

Возвращается огромное число месяцев

Даты в обратном порядке
Норма

Отрицательное значение или корректная обработка

Тревожный признак

Ошибка или неверный знак без контроля

Типичные ошибки при расчёте месяцев

Самая частая ошибка — считать месяцы как разность дат в днях, делённую на 30. Такой метод даёт погрешность до нескольких дней на длинных периодах и «теряет» месяцы на коротких: с 1 по 31 января получится один месяц, а с 1 февраля по 1 марта — тоже один, хотя длительность разная. Для кадровых и договорных расчётов это недопустимо.

Вторая ошибка — забыть поправку на день месяца при использовании простой формулы через Год и Месяц. Без неё период с 20 января по 10 февраля посчитается полным месяцем, что завысит стаж или срок. Третья типичная проблема — не обработать пустые даты и даты в обратном порядке, из-за чего в отчётах появляются аномальные значения.

Типичные ошибки
01
Деление разности дней на 30 — накапливает погрешность и искажает стаж и сроки
02
Отсутствие поправки на день месяца — неполный последний месяц засчитывается как полный
03
Игнорирование пустых дат — в отчётах появляются огромные значения месяцев
04
Смешение логик в одной базе: в одном отчёте полные месяцы, в другом разность номеров — данные не сходятся между собой

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

Чем РАЗНОСТЬДАТ в запросе отличается от формулы в коде?

РАЗНОСТЬДАТ с типом МЕСЯЦ считает пересечённые границы месяцев и не учитывает день месяца: между 31.01 и 01.02 вернёт 1. Формула в коде с поправкой на день считает именно полные месяцы. Выбор зависит от того, что требуется задаче.

Как посчитать месяцы с дробной частью, например 2,5 месяца?

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

Как учесть конец месяца, если начальная дата — 31-е число?

Добавьте проверку: если конечная дата равна КонецМесяца(Дата2) и её день меньше дня начальной даты, считайте последний месяц полным. Это стандартное правило для расчёта сроков «месяц в месяц».

Можно ли посчитать месяцы между датами без программирования?

В готовых отчётах — да, если добавить вычисляемое поле с РАЗНОСТЬДАТ в настройках СКД или воспользоваться консолью запросов. Для разовой проверки подойдёт любая обработка выполнения произвольного кода.

Почему в разных отчётах количество месяцев по одному сотруднику разное?

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

Итог

Что важно запомнить

Встроенной функции «месяцев между датами» в коде 1С нет: в запросах используйте РАЗНОСТЬДАТ с типом МЕСЯЦ, в модулях — формулу (Год2-Год1)*12 + Месяц2-Месяц1 с поправкой на день. Сначала определите, что считается месяцем, обработайте пустые и обратные даты и проверьте функцию на граничных парах вроде 31.01–28.02.