Расчет количества месяцев между двумя датами в 1С:Предприятие — задача, с которой регулярно сталкиваются бухгалтеры, кадровики и разработчики. Казалось бы, что может быть проще: взять разницу в днях и разделить на 30? Но такой подход даст погрешность, которая критична для начисления зарплаты, амортизации или финансовой отчетности. В этой статье разберем 5 точных методов — от стандартных функций платформы до авторских алгоритмов на встроенном языке.

Особенность работы с периодами в заключается в учете календарных месяцев, а не просто 30-дневных интервалов. Например, между 01.01.2026 и 31.01.2026 ровно 1 месяц, хотя разница в днях — 30. А между 15.01.2026 и 15.02.2026 тоже 1 месяц, хотя дней прошло 31. Стандартные математические операции здесь не работают — нужны специализированные инструменты.

Метод 1: Встроенная функция МесяцевМежду()

Самый простой способ — использовать функцию МесяцевМежду(), которая появилась в платформе 1С:Предприятие 8.3.10. Она автоматически учитывает календарные месяцы и корректно обрабатывает граничные случаи, например, когда начальная дата — конец месяца.

Синтаксис функции:

КоличествоМесяцев = МесяцевМежду(ДатаНачала, ДатаОкончания);

Примеры работы:

  • 📅 МесяцевМежду(Дата(2026,1,31), Дата(2026,2,28)) → вернет 1 (несмотря на разницу в 28 дней)
  • 📅 МесяцевМежду(Дата(2026,1,15), Дата(2026,3,15)) → вернет 2
  • 📅 МесяцевМежду(Дата(2026,2,29), Дата(2026,3,31)) → вернет 1 (учитывает високосный год)

Функция имеет необязательный третий параметр Точность, который определяет округление результата:

  • 🔢 Точность.Месяц — округление до целых месяцев (значение по умолчанию)
  • 🔢 Точность.День — результат в месяцах с дробной частью (например, 1.5 месяца)
💡

Если вам нужно получить количество полных месяцев (без округления в большую сторону), используйте параметр Точность.Месяц и функцию Цел():

ПолныхМесяцев = Цел(МесяцевМежду(Дата1, Дата2, Точность.Месяц));

Метод 2: Использование функции РазностьДат()

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

Алгоритм:

  1. Получите разницу в днях между датами.
  2. Преобразуйте дни в месяцы с учетом количества дней в каждом месяце.
  3. Скорректируйте результат для граничных дат (например, 31 января → 28 февраля).

Пример кода:

Процедура РассчитатьМесяцы(ДатаНачала, ДатаОкончания)

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

ТекущаяДата = ДатаНачала;

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

Пока ТекущаяДата < ДатаОкончания Цикл

СледующийМесяц = НачалоМесяца(ТекущаяДата) + Месяц;

Если СледующийМесяц > ДатаОкончания Тогда

Прервать;

КонецЕсли;

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

ТекущаяДата = СледующийМесяц;

КонецЦикла;

Возврат КоличествоМесяцев;

КонецПроцедуры

Этот метод точнее простого деления дней на 30, но требует учета високосных годов и разной длины месяцев. Например, при расчете между 31.01.2026 и 28.02.2026 результат будет 0 месяцев, хотя фактически прошел 1 месяц. Для корректной работы добавьте проверку:

Если День(ДатаНачала) > День(ДатаОкончания) И КонецМесяца(ДатаОкончания) = ДатаОкончания Тогда

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

КонецЕсли;

📊 Какой метод расчета месяцев вы используете чаще?
Встроенную функцию МесяцевМежду()
Самописный алгоритм
Функцию РазностьДат() с доработками
Другой вариант

Метод 3: Расчет через начало и конец месяцев

Еще один надежный способ — сравнивать начала месяцев. Этот подход гарантированно учитывает календарные месяцы, но может давать неожиданные результаты для дат внутри одного месяца (например, 01.01.2026 и 15.01.2026 вернут 0).

Алгоритм:

  1. Приведите обе даты к началу месяца с помощью НачалоМесяца().
  2. Посчитайте разницу в месяцах между полученными датами.
  3. Скорректируйте результат, если день окончания меньше дня начала.

Пример реализации:

Функция МесяцевВПериоде(ДатаНачала, ДатаОкончания)

НачалоПериода = НачалоМесяца(ДатаНачала);

КонецПериода = НачалоМесяца(ДатаОкончания);

Месяцев = (Год(КонецПериода) - Год(НачалоПериода)) * 12 + (Месяц(КонецПериода) - Месяц(НачалоПериода));

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

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

КонецЕсли;

Возврат Месяцев;

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

Особенности метода:

  • ✅ Точно учитывает календарные месяцы.
  • ⚠️ Требует дополнительной проверки для дат внутри одного месяца (см. корректировку с День()).
  • 🔄 Работает во всех версиях 1С:Предприятие 8.
Почему нельзя просто разделить дни на 30?

Если разделить разницу в днях на 30, для периода с 31.01.2026 по 28.02.2026 получится ~0.93 месяца, хотя фактически прошел 1 полный месяц. А для периода 01.01.2026–31.01.2026 результат будет 1 месяц, что верно. Такой подход дает погрешность до 10% в зависимости от выбранных дат.

Метод 4: Использование объекта Период

В некоторых конфигурациях (например, 1С:Бухгалтерия или 1С:Зарплата и Управление Персоналом) удобно работать с объектом Период, который предоставляет методы для анализа временных интервалов.

Пример использования:

ПериодРаботы = Новый Период(ДатаНачала, ДатаОкончания);

КоличествоМесяцев = ПериодРаботы.КоличествоМесяцев();

Преимущества метода:

  • 📊 Встроенная поддержка в типовых конфигурациях.
  • 🔧 Учитывает специфику расчетов (например, для начисления зарплаты или амортизации).
  • ⚡ Быстрее самописных алгоритмов за счет оптимизации платформы.

Ограничения:

  • ❌ Доступен не во всех конфигурациях (например, в 1С:Управление Торговлей может отсутствовать).
  • ❌ Логика расчета может отличаться в разных версиях конфигураций.

Убедитесь, что объект Период доступен в вашей конфигурации|Проверьте документацию — метод КоличествоМесяцев() может иметь особенности|Сравните результаты с другими методами для критичных расчетов|Учтите, что в некоторых конфигурациях периоды считаются включительно/исключительно-->

Метод 5: Программный расчет с учетом високосных годов

Для максимальной точности (например, в финансовых расчетах) можно реализовать полноценный алгоритм, учитывающий:

  • 📅 Количество дней в каждом месяце.
  • 🔄 Високосные годы.
  • 📆 Начало и конец месяцев.

Пример кода:

Функция ТочныеМесяцыМежду(ДатаНачала, ДатаОкончания)

Если ДатаНачала > ДатаОкончания Тогда

Возврат 0;

КонецЕсли;

Месяцев = 0;

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

Пока ТекущаяДата <= ДатаОкончания Цикл

СледующийМесяц = ТекущаяДата + Месяц;

Если СледующийМесяц > ДатаОкончания Тогда

Прервать;

КонецЕсли;

// Проверяем, что текущий месяц полностью входит в период

КонецТекущегоМесяца = КонецМесяца(ТекущаяДата);

Если КонецТекущегоМесяца <= ДатаОкончания Тогда

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

Иначе

// Частичный месяц

Если ДатаОкончания >= ТекущаяДата Тогда

Месяцев = Месяцев + (День(ДатаОкончания) / ДнейВМесяце(ТекущаяДата));

КонецЕсли;

Прервать;

КонецЕсли;

ТекущаяДата = СледующийМесяц;

КонецЦикла;

Возврат Месяцев;

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

Функция ДнейВМесяце(Дата)

Месяц = Месяц(Дата);

Год = Год(Дата);

Если Месяц = 2 Тогда

Если (Год % 4 = 0 И Год % 100 <> 0) Или (Год % 400 = 0) Тогда

Возврат 29; // Високосный год

Иначе

Возврат 28;

КонецЕсли;

ИначеЕсли Месяц В [4,6,9,11] Тогда

Возврат 30;

Иначе

Возврат 31;

КонецЕсли;

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

Этот алгоритм:

  • ✔️ Учитывает частичные месяцы (например, с 15.01.2026 по 10.02.2026 вернет ~1.5 месяца).
  • ✔️ Корректно обрабатывает високосные годы.
  • ✔️ Подходит для финансовых расчетов с дробной точностью.
💡

Для бухгалтерских расчетов (амортизация, резервы) используйте методы с дробной точностью (например, 1.5 месяца вместо округления до 2). Это соответствует требованиям ПБУ и НК РФ.

Сравнение методов: какой выбрать?

Выбор метода зависит от задачи, версии и требуемой точности. Ниже таблица сравнения:

Метод Точность Сложность реализации Поддержка старых версий Применимость
МесяцевМежду() ⭐⭐⭐⭐⭐ Только 8.3.10+ Универсальный
РазностьДат() + ручная обработка ⭐⭐⭐⭐ ⭐⭐⭐ Все версии Простые расчеты
Сравнение начал месяцев ⭐⭐⭐ ⭐⭐ Все версии Отчетность
Объект Период ⭐⭐⭐⭐ Зависит от конфигурации Типовые конфигурации
Полный программный расчет ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ Все версии Финансовые расчеты

Рекомендации по выбору:

  • 🔹 Для бухгалтерских отчетов (например, расчет среднесписочной численности) подойдет МесяцевМежду() или объект Период.
  • 🔹 Для зарплатных расчетов (например, компенсация за неиспользованный отпуск) используйте метод с дробной точностью.
  • 🔹 В устаревших конфигурациях (до 8.3.10) реализуйте алгоритм через РазностьДат().
💡

Если вам нужно посчитать количество месяцев между датами включительно (например, для расчета стажа), добавьте 1 к результату:

МесяцевВключительно = МесяцевМежду(ДатаНачала, ДатаОкончания) + 1;

Типичные ошибки и как их избежать

Даже опытные разработчики допускают ошибки при расчете месяцев в . Рассмотрим самые распространенные:

⚠️ Внимание: Если в расчете участвуют даты с 31 числом (например, 31.01.2026–28.02.2026), большинство методов вернут 0 месяцев вместо 1. Всегда проверяйте граничные случаи!

Ошибка 1: Игнорирование високосных лет

Если в периоде попадает 29 февраля, простые алгоритмы могут дать сбой. Например, разница между 28.02.2026 и 28.02.2026 — 1 год (12 месяцев), но если 2026 год високосный, а даты — 29.02.2026 и 28.02.2026, разница составит 11 месяцев и 28 дней.

Ошибка 2: Округление в большую сторону

Функция МесяцевМежду() с параметром Точность.Месяц округляет результат до целого числа. Например, для периода 15.01.2026–15.02.2026 она вернет 1, а для 15.01.2026–14.02.2026 — 0. Если вам нужны полные месяцы, используйте:

ПолныхМесяцев = Цел(МесяцевМежду(Дата1, Дата2, Точность.День));

Ошибка 3: Неучет временных зон

Если даты хранятся с учетом времени (например, 20260131235959), приведение к дате без времени может дать неверный результат. Всегда используйте:

ДатаБезВремени = НачалоДня(ДатаСВременем);
⚠️ Внимание: В конфигурациях с поддержкой международных стандартов (например, 1С:ERP) формат дат может отличаться. Перед расчетами приведите даты к локальному формату с помощью Формат(Дата, "ДЛФ=DT").

FAQ: Ответы на частые вопросы

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

В отчетах используйте выражение с функцией МесяцевМежду(). Например, для поля "Стаж" в отчете по сотрудникам:

Вычислить("МесяцевМежду(ДатаПриема, ТекущаяДата())")

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

(Год(ТекущаяДата()) - Год(ДатаПриема)) * 12 + (Месяц(ТекущаяДата()) - Месяц(ДатаПриема))
Почему МесяцевМежду() возвращает нецелое число?

Функция с параметром Точность.День возвращает дробное значение (например, 1.5 месяца). Чтобы получить целые месяцы:

  • Используйте Точность.Месяц (округление по правилам математики).
  • Примените Цел() для отбрасывания дробной части.
  • Используйте Окр() для округления до ближайшего целого.

Пример:

ЦелыхМесяцев = Цел(МесяцевМежду(Дата1, Дата2, Точность.День));
Как посчитать месяцы в периоде с учетом рабочих дней?

Для расчета рабочих месяцев (например, для начисления премии за отработанное время):

  1. Посчитайте общее количество месяцев (любым методом из статьи).
  2. Вычтите месяцы, в которых сотрудник был в отпуске или на больничном.

Пример кода:

РабочихМесяцев = МесяцевМежду(ДатаНачала, ДатаОкончания);

Для Каждого Отпуск Из ОтпускаСотрудника Цикл

Если Отпуск.ДатаНачала >= ДатаНачала И Отпуск.ДатаОкончания <= ДатаОкончания Тогда

РабочихМесяцев = РабочихМесяцев - МесяцевМежду(Отпуск.ДатаНачала, Отпуск.ДатаОкончания);

КонецЕсли;

КонецЦикла;

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

Да, но с оговорками:

  • Для линейного метода амортизации подойдет любой метод с целыми месяцами.
  • Для нелинейных методов (уменьшаемого остатка) используйте дробную точность.
  • Учтите, что согласно ПБУ 6/01, амортизация начисляется с 1-го числа месяца, следующего за месяцем ввода объекта в эксплуатацию.

Пример для амортизации:

ДатаНачалаАмортизации = НачалоМесяца(ДатаВвода) + Месяц;

КоличествоМесяцев = МесяцевМежду(ДатаНачалаАмортизации, ТекущаяДата());

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

Для расчета календарных месяцев за вычетом выходных (актуально для срочных договоров):

  1. Посчитайте общее количество дней в периоде.
  2. Вычтите количество суббот и воскресений.
  3. Преобразуйте оставшиеся дни в месяцы (условно 21 рабочий день = 1 месяц).

Пример кода:

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

Выходных = 0;

ТекущаяДата = ДатаНачала;

Пока ТекущаяДата <= ДатаОкончания Цикл

Если ДеньНедели(ТекущаяДата) В [6,7] Тогда // 6 - суббота, 7 - воскресенье

Выходных = Выходных + 1;

КонецЕсли;

ТекущаяДата = ТекущаяДата + День;

КонецЦикла;

РабочихДней = ДнейВПериоде - Выходных;

РабочихМесяцев = РабочихДней / 21; // Условно 21 рабочий день в месяце