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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Способ 1. Использование языка запросов 1С

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


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

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

Способ 2. Простая арифметическая формула в программном коде

Если расчет необходимо выполнить в модуле (на клиенте или сервере) без обращения к запросу, самым быстрым и распространенным способом является вычисление разницы лет и месяцев. Разберем логику этого метода:


// Предположим, Дата1 — это дата начала, Дата2 — дата окончания
КоличествоМесяцев = (Год(Дата2) - Год(Дата1)) * 12 + (Месяц(Дата2) - Месяц(Дата1));

Проанализируем ситуацию: эта формула возвращает количество полных календарных месяцев, прошедших между двумя датами, не обращая внимания на число месяца. Она эквивалентна работе функции в запросе. Например, для дат 01.10.2006 и 06.03.2020 результат составит 161 месяц.

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

Способ 3. Использование Библиотеки Стандартных Подсистем (БСП)

Современные конфигурации (такие как БП 3.0, УТ 11, ERP, ЗУП 3.1) содержат готовые механизмы в составе БСП. Проанализируем наиболее «чистый» программный способ, который избавляет разработчика от написания собственных формул:

Для решения задачи можно вызвать функцию общего модуля:

ОбщегоНазначенияКлиентСервер.РазностьДатВМесяцах(ДатаНачала, ДатаОкончания)

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

Способ 4. Расчет «честных» полных месяцев с учетом дней

Иногда требуется более точный расчет. Например, если человек отработал с 15 января по 10 февраля, прошел ли полный месяц? Формула из второго способа скажет, что прошел 1 месяц, но фактически это не так. Разберем алгоритм проверки завершенности месяца по дням:


Функция ПолучитьКоличествоПолныхМесяцев(ДатаНачала, ДатаОкончания)
    
    // Получаем предварительную разницу по календарным месяцам
    Результат = (Год(ДатаОкончания) - Год(ДатаНачала)) * 12 + (Месяц(ДатаОкончания) - Месяц(ДатаНачала));
    
    // Проверяем, наступило ли число месяца даты начала в месяце даты окончания
    Если День(ДатаОкончания) < День(ДатаНачала) Тогда
        // Если день окончания меньше дня начала, значит последний месяц еще не завершен
        Результат = Результат - 1;
    КонецЕсли;
    
    Возврат Макс(Результат, 0);
    
КонецФункции

Этот подход критически важен для кадрового учета или расчета процентов по кредитам, где важна фактическая длительность периода.

Способ 5. Использование функции ДобавитьМесяц() для итерационного расчета

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


Функция ТочнаяРазницаВМесяцах(ДатаН, ДатаК)
    
    КолМесяцев = 0;
    ВременнаяДата = ДатаН;
    
    Пока ДобавитьМесяц(ВременнаяДата, 1) <= ДатаК Цикл
        КолМесяцев = КолМесяцев + 1;
        ВременнаяДата = ДобавитьМесяц(ВременнаяДата, 1);
    КонецЦикла;
    
    Возврат КолМесяцев;
    
КонецФункции

Данный метод хорош тем, что платформа 1С самостоятельно обрабатывает сложные случаи: високосные годы и разное количество дней в месяцах (28, 30, 31). Функция ДобавитьМесяц() корректно «прыгает» на последнее число следующего месяца, если исходное число отсутствовало (например, с 31 января на 28/29 февраля).

Способ 6. Получение дробного количества месяцев

В некоторых экономических расчетах требуется получить результат вида «2.5 месяца». В 1С нет встроенного механизма для этого, поэтому выясним, как это реализовать математически. Обычно за основу берется среднее количество дней в месяце — 30.4375 (365.25 дней в году / 12 месяцев).


РазницаВСекундах = ДатаОкончания - ДатаНачала;
КоличествоДней = РазницаВСекундах / (24 * 60 * 60);
КоличествоМесяцев = КоличествоДней / 30.4375;

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

Резюме и рекомендации

Подведем итоги нашего анализа:

  1. Если нужно посчитать количество месяцев в запросе — используйте РАЗНОСТЬДАТ(..., МЕСЯЦ).
  2. Для простого программного расчета календарных месяцев используйте формулу (Год2-Год1)*12 + (Мес2-Мес1).
  3. Если в вашей конфигурации есть БСП, отдавайте предпочтение ОбщегоНазначенияКлиентСервер.РазностьДатВМесяцах().
  4. Для высокоточных расчетов (стаж, аренда) используйте алгоритм с проверкой День(Дата) или цикл с ДобавитьМесяц().
  5. Избегайте рекурсивных функций для расчета дат, так как при большой разнице периодов это может привести к переполнению стека вызовов системы.

Выбор конкретного метода зависит от требований к точности и контекста выполнения кода. Надеемся, что рассмотренные примеры помогут вам эффективно решать задачи по работе с периодами в 1С.

← На главную