Разработка и Конфигурация · 9 мин
Как посчитать разницу дат в 1С
Как посчитать разницу дат в 1С: вычитание дат, функции Запрос.РазностьДат, расчёт в днях, месяцах и годах, примеры кода и типичные ошибки разработчика.
Разница между датами — одна из самых частых задач в 1С: расчёт стажа сотрудника, срока хранения документа, количества дней просрочки по договору или возраста товара на складе. Способ вычисления зависит от того, где выполняется расчёт — в коде встроенного языка или в запросе — и от того, в каких единицах нужен результат: секундах, днях, месяцах или годах.
Главная особенность платформы 1С:Предприятие — при обычном вычитании двух дат оператором «минус» результат возвращается в секундах, а не в днях. Это источник большинства ошибок начинающих разработчиков: код работает без сообщений об ошибке, но выдаёт число в 86400 раз больше ожидаемого.
Для расчётов в запросах используется функция языка запросов РАЗНОСТЬДАТ, которая умеет возвращать разницу сразу в нужной единице измерения. Ниже разобраны оба подхода, примеры кода, обработка краевых случаев и типичные ошибки.
Вычитание дат оператором «минус» во встроенном языке
Самый простой способ — вычесть одну дату из другой напрямую. Платформа вернёт число — количество секунд между двумя моментами времени. Тип «Дата» в 1С хранит значение с точностью до секунды, поэтому и результат вычитания секундный.
ДатаНачала = '20260101';
ДатаОкончания = '20260315';
РазницаВСекундах = ДатаОкончания - ДатаНачала; // число секунд
РазницаВДнях = (ДатаОкончания - ДатаНачала) / 86400; // число дней
Число 86400 — это количество секунд в сутках (60 × 60 × 24). Деление на него переводит секунды в дни. Если даты содержат время, результат может быть дробным: например, 2,5 дня. Для получения целого числа дней используйте функцию Цел() или Окр() в зависимости от требуемой логики округления.
Если первая дата больше второй, результат будет отрицательным. Это удобно для проверки просрочки: отрицательная разница означает, что срок уже прошёл. Перед расчётом полезно явно проверять порядок дат, чтобы не получить неожиданный знак в отчёте.
Функция РАЗНОСТЬДАТ в запросах
Когда разница нужна в запросе — например, для отбора документов по сроку или вывода колонки «Дней просрочки» в отчёте — используется встроенная функция языка запросов РАЗНОСТЬДАТ. Она принимает три параметра: начальную дату, конечную дату и единицу измерения результата.
ВЫБРАТЬ
Реализация.Ссылка КАК Документ,
РАЗНОСТЬДАТ(Реализация.Дата, &ТекущаяДата, ДЕНЬ) КАК ДнейПрошло
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
В качестве третьего параметра доступны единицы: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Функция возвращает целое число — количество полных единиц между датами. То есть между 31 января и 1 февраля разница в месяцах равна нулю, хотя прошли сутки: полный месяц ещё не наступил.
Если даты переданы в обратном порядке (первая позже второй), результат будет отрицательным. В реальных запросах даты часто берутся из реквизитов документов, которые могут быть пустыми — пустая дата ('00010101') даст огромное значение разности. Перед вычислением стоит отфильтровать такие записи условием ГДЕ или обработать через ВЫБОР.
РАЗНОСТЬДАТ(Договор.ДатаНачала, Договор.ДатаОкончания, МЕСЯЦ) КАК СрокМесяцевРасчёт разницы в месяцах и годах: стаж и возраст
Расчёт полных лет или месяцев сложнее, чем деление секунд, потому что месяцы имеют разную длину. Например, стаж сотрудника с 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 во всех единицах
Ненулевое значение или ошибка
86400 секунд или 1 день
86400 выдано как «дни»
0 полных месяцев
Результат 1 месяц
Запись отфильтрована или обработана
Огромное число в отчёте
Типичные ошибки при расчёте разницы дат
Большинство проблем связано не со сложностью задачи, а с невнимательностью к единицам измерения и граничным значениям. Ниже собраны ошибки, которые встречаются чаще всего.
Отдельно стоит упомянуть работу с часовыми поясами в распределённых системах. Если сервер и клиент находятся в разных часовых поясах, «текущая дата» может отличаться, и расчёт просрочки даст разные результаты у разных пользователей. В таких случаях фиксируйте, относительно какого момента времени выполняется расчёт.
Выбор подхода под задачу
Для разовых вычислений в коде достаточно оператора «минус» с делением на 86400. Для отчётов и отборов по срокам удобнее РАЗНОСТЬДАТ в запросе — она выполняется на уровне СУБД и не требует обхода выборки в цикле. Для календарных периодов (месяцы, годы, стаж) используйте специализированные функции, а не арифметику дней.
Как выбрать способ расчёта
При сомнениях в корректности расчёта сравните результат с ручным подсчётом на календаре для нескольких контрольных пар дат, включая границы месяцев и високосный год. Это быстрее, чем отладка готового отчёта с тысячами строк.
Что важно запомнить
Вычитание дат в коде 1С даёт секунды — для дней делите на 86400. В запросах применяйте РАЗНОСТЬДАТ с явной единицей измерения, помня, что считаются только полные периоды. Для сдвига дат на месяцы используйте ДобавитьМесяц. Всегда проверяйте пустые даты и граничные случаи.
Частые вопросы
Почему при вычитании дат получается огромное число?
Потому что результат выражен в секундах, а не в днях. Разделите значение на 86400, чтобы получить дни. Если число выглядит как миллионы лет разницы — проверьте, не участвует ли в расчёте пустая дата '00010101'.
Как получить разницу в днях без учёта времени?
Отбросьте время у обеих дат перед вычитанием, например через НачалоДня(Дата). Тогда деление секунд на 86400 даст целое число дней без дробной части. В запросе можно использовать НАЧАЛОПЕРИОДА(Дата, ДЕНЬ).
Можно ли посчитать разницу в рабочих днях?
Штатной функции для этого нет. Нужно использовать регистр сведений с производственным календарём (в типовых конфигурациях он есть) и считать количество рабочих дней между датами по календарю, либо перебирать дни в цикле с проверкой.
Что вернёт РАЗНОСТЬДАТ, если даты стоят в обратном порядке?
Отрицательное число полных единиц. Это можно использовать как признак просрочки, но лучше явно контролировать порядок дат в логике отчёта, чтобы не запутать пользователей знаком минус.
Как посчитать разницу дат в СКД без изменения запроса?
Добавьте вычисляемое поле в наборе данных или используйте выражение на языке выражений СКД с функцией РазностьДат. Однако надёжнее вычислить разницу прямо в запросе через РАЗНОСТЬДАТ — так расчёт выполнится на стороне СУБД.
Учитывается ли високосный год при расчётах?
Да, платформа корректно работает с календарём: 29 февраля учитывается и при вычитании дат, и в функции ДобавитьМесяц. Ошибки возникают только при ручном делении дней на фиксированные 30 или 365 — такой подход накапливает погрешность.