Разработка и Конфигурация · 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Определите, что считать месяцем: календарную разницу или полные месяцы
- 2Для календарной разницы используйте РазностьДат с параметром "Месяц"
- 3Для полных месяцев добавьте корректировку по дню месяца
- 4Проверьте результат на граничных датах: 31.01–28.02, 15.01–15.02, 01.01–31.12
- 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) в расчёте даст огромное число месяцев, поэтому перед вычислением проверяйте ЗначениеЗаполнено() для обеих дат.
Как проверить результат
Результат 0
Результат 1 или ошибка
Результат 1
0 или 2
0 полных месяцев, 1 календарный
Отрицательное число или 11
Отрицательное значение или явная обработка
Аварийное завершение или молчаливый ноль
FAQ
Чем отличается РазностьДат с "Месяц" от деления дней на 30?
РазностьДат считает разницу календарных номеров месяцев и всегда возвращает целое. Деление дней на 30 даёт дробное значение, зависящее от фактической длины периода. Для договорных сроков обычно нужен первый вариант, для финансовых пропорций — второй.
Как посчитать месяцы и остаток дней отдельно?
Сначала вычислите полные месяцы с корректировкой по дню месяца, затем прибавьте это число месяцев к начальной дате через ДобавитьМесяц() и посчитайте РазностьДат в днях от полученной даты до конечной.
Работает ли РазностьДат на клиенте в управляемых формах?
Да, функция доступна на тонком и веб-клиенте, поэтому расчёт можно выполнять без вызова сервера. Это удобно для мгновенного показа результата при изменении дат в форме.
Что вернёт расчёт, если одна из дат не заполнена?
Пустая дата в 1С — это 01.01.0001. РазностьДат вернёт огромное число месяцев без ошибки, поэтому перед расчётом всегда проверяйте обе даты функцией ЗначениеЗаполнено().
Как посчитать месяцы между датами в СКД?
В схеме компоновки доступен тот же оператор РАЗНОСТЬДАТ в выражении вычисляемого поля или в тексте запроса набора данных. Для полных месяцев добавьте корректировку через ВЫБОР с функцией ДЕНЬ().
Есть ли в типовых конфигурациях готовые функции для расчёта стажа?
Да, в конфигурациях линии ЗУП есть общие модули для работы со стажем, которые учитывают принятые правила подсчёта периодов. Перед написанием собственного алгоритма проверьте наличие типовых процедур — это снизит риск расхождений с отчётностью.
Что важно запомнить
Для календарной разницы месяцев используйте РазностьДат с параметром "Месяц" или РАЗНОСТЬДАТ в запросах. Для полных месяцев добавьте корректировку по дню месяца. Всегда проверяйте заполненность дат и тестируйте граничные случаи.