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

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

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

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

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

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

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

Функция РазностьДат — базовый способ

Функция РазностьДат(Дата1; Дата2; ЕдиницаИзмерения) возвращает разницу между двумя датами в указанной единице: секундах, минутах, часах, днях, месяцах, кварталах или годах. Для месяцев третий параметр задаётся строкой "Месяц". Функция доступна и в тонком, и в толстом клиенте, и на сервере.

ДатаНачала = Дата(2026, 1, 15);

ДатаОкончания = Дата(2026, 10, 20);

КоличествоМесяцев = РазностьДат(ДатаНачала, ДатаОкончания, "Месяц");

// Результат: 9

Функция считает разницу по календарным границам месяцев: результат — это разница порядковых номеров месяцев, а не число полностью прожитых месяцев. Между 31 января и 1 февраля она вернёт 1, хотя прошли сутки. Если даты перепутаны местами (начало позже окончания), результат будет отрицательным — это стоит учитывать или обрабатывать явно.

Расчёт полных месяцев с учётом дня месяца

Когда требуется число именно полных месяцев (как при расчёте стажа или срока владения), простой разницы месяцев недостаточно. Например, с 20 марта по 10 мая полных месяцев — один, хотя разница номеров месяцев равна двум. Решение — вычесть единицу, если день конечной даты меньше дня начальной.

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

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

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

Месяцев = Месяцев - 1;

КонецЕсли;

Такой подход даёт детерминированный результат и легко тестируется. Обратите внимание на граничный случай с концом месяца: период с 31 января по 28 февраля формально не содержит полного месяца по этой формуле, хотя интуитивно многие считают его полным. Если бизнес-правила требуют иначе, добавьте проверку «день конечной даты — последний день месяца» через КонецМесяца().

Порядок действий
  1. 1
    Определите, что считать месяцем: календарную разницу или полные месяцы
  2. 2
    Для календарной разницы используйте РазностьДат с параметром "Месяц"
  3. 3
    Для полных месяцев добавьте корректировку по дню месяца
  4. 4
    Проверьте результат на граничных датах: 31.01–28.02, 15.01–15.02, 01.01–31.12
  5. 5
    Обработайте случай, когда начальная дата позже конечной

Расчёт в запросе через РАЗНОСТЬДАТ

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

ВЫБРАТЬ

Договоры.Ссылка КАК Договор,

РАЗНОСТЬДАТ(&ТекущаяДата, Договоры.ДатаОкончания, МЕСЯЦ) КАК МесяцевОсталось

ИЗ

Справочник.ДоговорыКонтрагентов КАК Договоры

ГДЕ

Договоры.ДатаОкончания > &ТекущаяДата

Как и РазностьДат, оператор возвращает целое число календарных месяцев. Для полных месяцев придётся добавить вычисляемое поле с ВЫБОР ... КОГДА ДЕНЬ(...) либо доработать результат уже в коде после выполнения запроса. Учтите, что функция даты ДЕНЬ() в запросах доступна, поэтому корректировку реально выполнить и на уровне запроса.

Сравнение вариантов

РазностьДат в коде

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

Ручной расчёт через Год/Месяц/День

Полный контроль над логикой полных месяцев. Требует аккуратной обработки граничных дат

РАЗНОСТЬДАТ в запросе

Оптимально для выборок по множеству строк. Сложнее реализовать нестандартную логику округления

Запрос к календарю/регистру периодов

Нужен, когда важны рабочие месяцы по производственному календарю, а не календарные

Дробные месяцы и альтернативные сценарии

Дробное количество месяцев

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

Дней = РазностьДат(ДатаНачала, ДатаОкончания, "День");

МесяцевДробно = Окр(Дней / 30.4375, 2);

Месяцы по производственному календарю

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

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

После реализации обязательно прогоните расчёт на контрольных парах дат. Проверьте: одинаковые даты (должно быть 0), ровно месяц (15.01–15.02), переход через год (15.12–15.01), границы месяцев (31.01–28.02), обратный порядок дат. Расхождение хотя бы в одном случае — признак ошибки в логике корректировки.

Частая ошибка — забыть, что РазностьДат с единицей «Месяц» игнорирует дни. Разработчик ожидает «полных месяцев», а получает календарную разницу, и в отчётах появляется лишний месяц. Вторая типичная проблема — пустые даты: Дата(1,1,1) в расчёте даст огромное число месяцев, поэтому перед вычислением проверяйте ЗначениеЗаполнено() для обеих дат.

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

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

Одинаковые даты начала и конца
Норма

Результат 0

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

Результат 1 или ошибка

Ровно один месяц (10.03–10.04)
Норма

Результат 1

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

0 или 2

Переход через год (20.12–10.01)
Норма

0 полных месяцев, 1 календарный

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

Отрицательное число или 11

Обратный порядок дат
Норма

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

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

Аварийное завершение или молчаливый ноль

FAQ

Чем отличается РазностьДат с "Месяц" от деления дней на 30?

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

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

Сначала вычислите полные месяцы с корректировкой по дню месяца, затем прибавьте это число месяцев к начальной дате через ДобавитьМесяц() и посчитайте РазностьДат в днях от полученной даты до конечной.

Работает ли РазностьДат на клиенте в управляемых формах?

Да, функция доступна на тонком и веб-клиенте, поэтому расчёт можно выполнять без вызова сервера. Это удобно для мгновенного показа результата при изменении дат в форме.

Что вернёт расчёт, если одна из дат не заполнена?

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

Как посчитать месяцы между датами в СКД?

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

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

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

Итог

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

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