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

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

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

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

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

Поэтому используются несколько подходов: функция РазностьДат() в запросах, комбинация ДобавитьМесяц() с циклом в коде, ручной расчёт через год и месяц даты, а также типовые механизмы БСП (Библиотека стандартных подсистем). У каждого способа есть свои ограничения: например, «месяц» в запросе — это календарное понятие, а не 30 дней, и результаты при граничных датах могут отличаться от ожиданий.

Ниже разобраны рабочие варианты с примерами кода, условиями выбора и проверкой результата. Примеры применимы к платформе 8.3 и типовым конфигурациям.

Как 1С хранит даты и почему нет прямого вычитания месяцев

Тип «Дата» в 1С хранится с точностью до секунды. Операция Дата2 - Дата1 возвращает число — разность в секундах. Чтобы получить дни, результат делят на 86400, но с месяцами такой приём не работает: месяцы имеют разную длину (28–31 день), поэтому «средний месяц» из секунд даст погрешность.

Из-за этого платформа предлагает отдельные инструменты: функции Месяц(), Год(), ДобавитьМесяц() в языке и РазностьДат() в языке запросов. Каждая решает задачу по-своему, и выбор зависит от того, нужен ли календарный результат или количество полностью прошедших месяцев.

Способ 1: РазностьДат в запросе

Самый короткий путь — запрос с функцией РАЗНОСТЬДАТ(ДатаНачала, ДатаОкончания, МЕСЯЦ). Третий параметр задаёт единицу измерения: можно получить ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД, СЕКУНДА и другие.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

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

Запрос.УстановитьПараметр("ДатаНачала", Дата(2026, 1, 15));

Запрос.УстановитьПараметр("ДатаОкончания", Дата(2026, 3, 10));

Результат = Запрос.Выполнить().Выгрузить();

КоличествоМесяцев = Результат[0].КоличествоМесяцев;

Важная особенность: РазностьДат считает количество границ месяцев между датами, а не полных прожитых месяцев. Например, между 31 января и 1 февраля разность в месяцах равна 1, хотя прошли сутки. А между 15 января и 14 февраля — тоже 1. Поэтому для расчёта стажа или сроков с точностью до дня этот способ нужно дополнять проверкой дня месяца.

Способ 2: расчёт через Год и Месяц в коде

Если запрос не нужен, количество календарных месяцев между датами легко получить формулой через годы и месяцы:

КоличествоМесяцев = (Год(ДатаОкончания) - Год(ДатаНачала)) * 12

+ (Месяц(ДатаОкончания) - Месяц(ДатаНачала));

Этот вариант даёт тот же результат, что и РазностьДат(..., МЕСЯЦ): разность номеров месяцев без учёта дней. Он удобен в модуле объекта или формы, где даты уже есть в реквизитах и формировать запрос ради одного числа избыточно.

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

КоличествоМесяцев = (Год(ДатаОкончания) - Год(ДатаНачала)) * 12

+ (Месяц(ДатаОкончания) - Месяц(ДатаНачала));

Если День(ДатаОкончания) < День(ДатаНачала) Тогда

КоличествоМесяцев = КоличествоМесяцев - 1;

КонецЕсли;

Такой расчёт соответствует бытовому пониманию «полных месяцев»: с 10 января по 9 февраля — 0 полных месяцев, с 10 января по 10 февраля — 1.

Способ 3: цикл с ДобавитьМесяц

Функция ДобавитьМесяц(Дата, ЧислоМесяцев) сдвигает дату на заданное число месяцев, корректно обрабатывая конец месяца: ДобавитьМесяц(Дата(2026,1,31), 1) вернёт 29.02.2026 (в високосный год), а не несуществующее 31 февраля. На этом строится итеративный подсчёт:

КоличествоМесяцев = 0;

ТекДата = ДатаНачала;

Пока ДобавитьМесяц(ТекДата, 1) <= ДатаОкончания Цикл

ТекДата = ДобавитьМесяц(ТекДата, 1);

КоличествоМесяцев = КоличествоМесяцев + 1;

КонецЦикла;

Способ нагляден и безопасен для коротких периодов (месяцы, годы), но для интервалов в десятки лет цикл выполнит сотни итераций — в этом случае быстрее формула из предыдущего раздела. Цикл оправдан, когда на каждом шаге нужно не только посчитать, но и что-то сделать: сформировать строку таблицы по месяцам, рассчитать амортизацию за месяц и т.п.

ДобавитьМесяц корректно обрабатывает 29–31 числа: при сдвиге с конца длинного месяца дата «приземляется» на последний день короткого. Поэтому цепочка сдвигов с 31 января пойдёт через 29/28 февраля, а дальше день месяца уже не восстановится до 31 — учитывайте это в графиках платежей.
ПЗ
Практическое замечание

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

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

ТекМесяц = НачалоМесяца(ДатаНачала);

Пока ТекМесяц <= ДатаОкончания Цикл

НоваяСтрока = ТаблицаМесяцев.Добавить();

НоваяСтрока.Месяц = ТекМесяц;

ТекМесяц = ДобавитьМесяц(ТекМесяц, 1);

КонецЦикла;

Количество строк в итоговой таблице и будет количеством месяцев, которых касается период (включая неполные первый и последний). Этот подход используется в графиках начислений, плановых платежах и отчётах по периодам.

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

Порядок действий при выборе способа
  1. 1
    Определите, что считать: календарные месяцы (смена номера) или полные месяцы с учётом дней
  2. 2
    Для запроса используйте РазностьДат(Дата1, Дата2, МЕСЯЦ)
  3. 3
    Для кода без запроса примените формулу (Год2-Год1)*12 + (Месяц2-Месяц1)
  4. 4
    Если нужны полные месяцы — добавьте корректировку по дню месяца
  5. 5
    Проверьте результат на граничных датах: 31.01–01.02, 15.01–14.02, високосный февраль

Проверка результата и типичные ошибки

Главный источник ошибок — разные ожидания от слова «месяц». Бухгалтер под «3 месяца отсрочки» понимает полные месяцы, а РазностьДат вернёт 3 даже для периода с 28 февраля по 1 марта при определённых границах. Всегда согласовывайте методику расчёта с постановкой задачи и фиксируйте её в комментарии к коду.

Вторая группа ошибок — пустые и незаполненные даты. Если реквизит даты не заполнен, функции Год(), Месяц() вернут значения от даты 01.01.0001, и результат будет огромным числом. Перед расчётом проверяйте даты на заполненность и на корректный порядок (начало раньше окончания).

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

Для контроля используйте простой набор тестовых пар дат с известным ответом: ровно год (12 месяцев), ровно месяц (1), граничные случаи вроде 31.01–28.02 и 15.01–14.02. Если алгоритм проходит эти точки, он надёжен и на произвольных данных.

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

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

Период 10.01.2026–10.02.2026
Норма

Полных месяцев: 1; календарных: 1

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

0 или 2 — ошибка в корректировке по дню

Период 31.01.2026–01.02.2026
Норма

РазностьДат даёт 1, полных месяцев — 0

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

Ожидание «0» от РазностьДат без учёта её логики

Пустая дата окончания
Норма

Расчёт не выполняется, выводится предупреждение

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

Огромное число месяцев от даты 01.01.0001

Что выбрать в разных ситуациях

Единственного «правильного» способа нет — выбор зависит от контекста. В отчётах и СКД логичнее РазностьДат на уровне запроса: это быстрее и не требует обхода выборки. В модуле документа с парой дат достаточно формулы через Год() и Месяц(). Для построения помесячных графиков незаменим цикл с ДобавитьМесяц().

Сравнение способов

РазностьДат в запросе

Подходит для отчётов и СКД; быстро, но считает только календарные месяцы без учёта дней

Формула через Год и Месяц

Удобна в коде без запроса; легко дополняется корректировкой на полные месяцы

Цикл с ДобавитьМесяц

Нужен для помесячного обхода периода; на длинных интервалах медленнее формулы

Типовые механизмы БСП и ЗУП

Предпочтительны в типовых конфигурациях: согласованы с отчётностью, но требуют изучения API

При сомнениях ориентируйтесь на постановку задачи: если в ней сказано «срок действия в месяцах» — считайте полные месяцы с корректировкой по дню; если «количество месяцев периода» для отчёта — подойдёт календарная разность.

Итог

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

Прямого вычитания месяцев в 1С нет: используйте РазностьДат(..., МЕСЯЦ) в запросах, формулу (Год2-Год1)*12+(Месяц2-Месяц1) в коде и ДобавитьМесяц для помесячного обхода. Различайте календарные и полные месяцы и проверяйте даты на заполненность.

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

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

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

Как получить только полные месяцы между датами?

Посчитайте разность через (Год2-Год1)*12 + (Месяц2-Месяц1), затем сравните день конечной и начальной даты: если день окончания меньше дня начала, вычтите 1. Так с 10.01 по 09.02 получится 0 полных месяцев, а с 10.01 по 10.02 — один.

Что вернёт ДобавитьМесяц для даты 31 января?

Функция вернёт последний день февраля (28 или 29 число в високосный год), так как 31 февраля не существует. Это корректное поведение платформы, но при цепочке сдвигов исходный день месяца не восстановится.

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

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

Почему расчёт даёт огромное число месяцев?

Скорее всего, одна из дат не заполнена: пустая дата равна 01.01.0001, и разность с реальной датой составит тысячи месяцев. Добавьте проверку ЗначениеЗаполнено(Дата) перед расчётом и контроль порядка дат.

Есть ли готовые функции расчёта месяцев в типовых конфигурациях?

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