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

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

Как посчитать разницу дат в 1С

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

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

Главная особенность платформы 1С:Предприятие — при обычном вычитании двух дат оператором «минус» результат возвращается в секундах, а не в днях. Это источник большинства ошибок начинающих разработчиков: код работает без сообщений об ошибке, но выдаёт число в 86400 раз больше ожидаемого.

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

Вычитание дат оператором «минус» во встроенном языке

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

ДатаНачала = '20260101';

ДатаОкончания = '20260315';

РазницаВСекундах = ДатаОкончания - ДатаНачала; // число секунд

РазницаВДнях = (ДатаОкончания - ДатаНачала) / 86400; // число дней

Число 86400 — это количество секунд в сутках (60 × 60 × 24). Деление на него переводит секунды в дни. Если даты содержат время, результат может быть дробным: например, 2,5 дня. Для получения целого числа дней используйте функцию Цел() или Окр() в зависимости от требуемой логики округления.

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

Функция РАЗНОСТЬДАТ в запросах

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

ВЫБРАТЬ

Реализация.Ссылка КАК Документ,

РАЗНОСТЬДАТ(Реализация.Дата, &ТекущаяДата, ДЕНЬ) КАК ДнейПрошло

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

В качестве третьего параметра доступны единицы: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Функция возвращает целое число — количество полных единиц между датами. То есть между 31 января и 1 февраля разница в месяцах равна нулю, хотя прошли сутки: полный месяц ещё не наступил.

Если даты переданы в обратном порядке (первая позже второй), результат будет отрицательным. В реальных запросах даты часто берутся из реквизитов документов, которые могут быть пустыми — пустая дата ('00010101') даст огромное значение разности. Перед вычислением стоит отфильтровать такие записи условием ГДЕ или обработать через ВЫБОР.

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

Расчёт разницы в месяцах и годах: стаж и возраст

Расчёт полных лет или месяцев сложнее, чем деление секунд, потому что месяцы имеют разную длину. Например, стаж сотрудника с 15 марта 2020 по 10 марта 2026 — это 3 полных года и 11 месяцев, а не 4 года, хотя разница в днях близка к четырём годам.

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

// Расчёт полных лет в коде

ПолныхЛет = Год(Дата2) - Год(Дата1);

Если Месяц(Дата2) < Месяц(Дата1)

Или (Месяц(Дата2) = Месяц(Дата1) И День(Дата2) < День(Дата1)) Тогда

ПолныхЛет = ПолныхЛет - 1;

КонецЕсли;

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

Добавление и вычитание периодов: ДобавитьМесяц

Обратная задача — получить дату, сдвинутую на заданный период. Для дней достаточно прибавить нужное число секунд: Дата + 7 * 86400 добавит неделю. Для месяцев такой подход не работает из-за разной длины месяцев, поэтому во встроенном языке есть функция ДобавитьМесяц.

НоваяДата = ДобавитьМесяц('20260131', 1); // 29.02.2026 — корректный перенос на конец февраля

ДобавитьМесяц корректно обрабатывает конец месяца: если исходная дата — 31 января, то прибавление месяца даст последний день февраля, а не несуществующее 31 февраля. Функция принимает и отрицательные значения для сдвига назад. В языке запросов аналогичная функция называется ДОБАВИТЬКДАТЕ с указанием единицы измерения.

Связка РАЗНОСТЬДАТ и ДОБАВИТЬКДАТЕ позволяет проверять расчёты: если добавить к первой дате вычисленную разницу, должна получиться вторая дата (с точностью до неполных единиц).

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

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

Обязательно проверьте граничные случаи: переход через високосный февраль, даты с временем 23:59:59 и 00:00:00, пустые даты и даты в обратном порядке. Именно на этих данных расчёты ломаются чаще всего.

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

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

Разница одинаковых дат
Норма

0 во всех единицах

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

Ненулевое значение или ошибка

Соседние сутки 01.03 и 02.03
Норма

86400 секунд или 1 день

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

86400 выдано как «дни»

31.01 и 01.02 в месяцах
Норма

0 полных месяцев

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

Результат 1 месяц

Пустая дата в расчёте
Норма

Запись отфильтрована или обработана

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

Огромное число в отчёте

Типичные ошибки при расчёте разницы дат

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

Типичные ошибки
01
Использование секунд как дней: результат вычитания дат не делится на 86400, и сроки в отчётах завышаются в десятки тысяч раз
02
Расчёт месяцев делением дней на 30: из-за разной длины месяцев накапливается погрешность, для месяцев нужны РАЗНОСТЬДАТ или ДобавитьМесяц
03
Игнорирование пустых дат: '00010101' в реквизите даёт огромную разность и портит итоги отчёта
04
Ожидание дробного результата от РАЗНОСТЬДАТ: функция возвращает только полные единицы, неполные периоды отбрасываются
05
Сравнение дат с временем и без: дата 01.03 00:00:00 и 01.03 15:30:00 дают разные результаты при округлении до дней

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

Выбор подхода под задачу

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

Маршрут решения

Как выбрать способ расчёта

Нужна разница в днях или часах в коде модуляВычтите даты оператором «минус» и разделите на 86400 (или 3600 для часов)
Разница нужна в запросе или отчёте СКДИспользуйте РАЗНОСТЬДАТ с нужной единицей измерения
Считаются полные месяцы или годы (стаж, возраст)Применяйте РАЗНОСТЬДАТ с корректировкой на неполный период
Нужно сдвинуть дату на месяцыИспользуйте ДобавитьМесяц или ДОБАВИТЬКДАТЕ, а не арифметику секунд

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

Итог

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

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

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

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

Потому что результат выражен в секундах, а не в днях. Разделите значение на 86400, чтобы получить дни. Если число выглядит как миллионы лет разницы — проверьте, не участвует ли в расчёте пустая дата '00010101'.

Как получить разницу в днях без учёта времени?

Отбросьте время у обеих дат перед вычитанием, например через НачалоДня(Дата). Тогда деление секунд на 86400 даст целое число дней без дробной части. В запросе можно использовать НАЧАЛОПЕРИОДА(Дата, ДЕНЬ).

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

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

Что вернёт РАЗНОСТЬДАТ, если даты стоят в обратном порядке?

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

Как посчитать разницу дат в СКД без изменения запроса?

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

Учитывается ли високосный год при расчётах?

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