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

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

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

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

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

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

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

Вычитание дат оператором: разность в секундах

Самый простой способ — обычное вычитание. Если из одного значения типа Дата вычесть другое, результатом будет число секунд между ними. Это удобно, когда нужно измерить длительность операции с точностью до секунды, например время выполнения обработки.

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

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

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

РазностьДней = РазностьСекунд / 86400; // 4,083 дня

Чтобы получить целое количество дней, делите результат на 86400 (60 × 60 × 24) и при необходимости округляйте через Цел(). Учтите: если даты содержат время, результат почти никогда не будет целым числом дней. Для расчёта по календарным дням без учёта времени предварительно отсеките время функцией НачалоДня.

bsl
РазностьДней = Цел((НачалоДня(ДатаОкончания) - НачалоДня(ДатаНачала)) / 86400);

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

Функция РазностьДат: месяцы, кварталы и годы

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

// Синтаксис: РазностьДат(Дата1, Дата2, ТипРазности)

Месяцев = РазностьДат('20260115', '20260720', ТипРазностиДат.Месяц); // 6

Дней = РазностьДат('20260115', '20260720', ТипРазностиДат.День);

Параметр ТипРазности принимает значения перечисления ТипРазностиДат: Секунда, Минута, Час, День, Месяц, Квартал, Год. Важная особенность: функция считает количество полных границ периода между датами. Между 31 января и 1 февраля разность в месяцах равна 1, хотя прошёл всего один день. Это нужно учитывать при расчёте стажа или сроков оплаты.

Если нужна разность в днях без учёта времени, комбинируйте функцию с НачалоДня — иначе разница в одну секунду между датами разных дней даст результат 1 день, что обычно корректно, но при сравнении дат внутри одного дня даст 0 даже при разнице в 23 часа.

Расчёт разности дат в запросе

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

ВЫБРАТЬ

Заказ.Ссылка,

РАЗНОСТЬДАТ(Заказ.Дата, &ТекущаяДата, ДЕНЬ) КАК ДнейСЗаказа,

РАЗНОСТЬДАТ(Заказ.ДатаОтгрузки, Заказ.ДатаОплаты, ДЕНЬ) КАК ДнейОтсрочки

ИЗ

Документ.ЗаказПокупателя КАК Заказ

Допустимые единицы: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Функция удобна для отборов — например, выбрать все документы с просрочкой более 30 дней, поместив условие РАЗНОСТЬДАТ в секцию ГДЕ или ИМЕЮЩИЕ.

Как посчитать просрочку в запросе
  1. 1
    Добавьте в выборку РАЗНОСТЬДАТ(ДатаДокумента, &ТекущаяДата, ДЕНЬ) КАК ДнейПросрочки
  2. 2
    Передайте параметр &ТекущаяДата через УстановитьПараметр — функция ТекущаяДата() в запросе недоступна
  3. 3
    Добавьте условие ГДЕ РАЗНОСТЬДАТ(...) > 30 для отбора просроченных
  4. 4
    Проверьте результат на документе с известными датами

Обратите внимание: в запросе нельзя вызвать ТекущаяДата() напрямую. Дату сравнения передавайте параметром из кода. Также помните, что пустая дата (01.01.0001) в расчёте даст огромное значение — фильтруйте записи с незаполненными датами через ЕСТЬ NULL или сравнение с пустой датой.

Разность дат в СКД и отчётах

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

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

Где считать разность дат

Оператор вычитания в коде

Подходит для секунд и точной длительности; требует ручного пересчёта в дни

РазностьДат в коде

Подходит для календарных периодов в модуле; не работает внутри запроса

РАЗНОСТЬДАТ в запросе

Оптимально для отборов и отчётов; требует передачи текущей даты параметром

Вычисляемое поле СКД

Подходит для отчётов без изменения запроса; медленнее при больших объёмах

Крайние случаи: время, високосные годы и пустые даты

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

Вторая группа проблем — состав даты. Если документ хранит дату со временем, разность между «сегодня 09:00» и «завтра 18:00» составит 1 день по функции РазностьДат с типом День, но 33 часа по точному вычитанию. Определитесь заранее, что для вашей задачи является корректным результатом, и приводите даты к началу или концу дня.

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

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

Разность между 01.03 и 02.03
Норма

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

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

0 дней или отрицательное значение

Разность в месяцах между 31.01 и 01.02
Норма

1 месяц (граница пересечена)

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

Ожидание 0 месяцев как «полных»

Расчёт с пустой датой
Норма

Ветка обработки отсутствующего значения

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

Результат в сотни тысяч дней

Отрицательная разность
Норма

Осознанное поведение с проверкой порядка дат

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

Молчаливый минус в отчёте

Високосный год влияет на расчёты через февраль: между 28.02 и 01.03 високосного года проходит два дня, а не один. Функции 1С учитывают это автоматически, но если вы пишете собственный пересчёт дней в месяцах «вручную», такие места нужно тестировать отдельно.

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

Самая распространённая ошибка — забыть, что вычитание даёт секунды, и вывести в отчёт число вроде 2592000 вместо 30 дней. Вторая по частоте — использование РазностьДат с типом Месяц для расчёта «полных» месяцев стажа, из-за чего сотруднику, принятому 31 января, 1 февраля уже «насчитается» месяц.

Типичные ошибки
01
Вывод секунд вместо дней — делите результат вычитания на 86400
02
Ожидание полных периодов от РазностьДат — функция считает границы периодов
03
Игнорирование времени в датах — приводите к НачалоДня при расчёте по календарю
04
Расчёт без проверки пустых дат — добавляйте ЗначениеЗаполнено
05
Вызов ТекущаяДата() в запросе — передавайте дату параметром

Ещё одна ловушка — хранение разности дат в реквизите типа Дата. Разность — это число (длительность), а не дата. Попытка присвоить результат вычитания реквизиту с типом Дата приведёт к ошибке преобразования или бессмысленному значению. Используйте числовой реквизит с подходящей точностью.

Итог

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

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

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

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

Приведите обе даты к началу дня и разделите разность в секундах на 86400: Цел((НачалоДня(Дата2) - НачалоДня(Дата1)) / 86400). Так разница во времени не повлияет на результат.

Почему РазностьДат между 31 января и 1 февраля даёт 1 месяц?

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

Можно ли использовать ТекущаяДата() внутри запроса?

Нет, в языке запросов эта функция недоступна. Передайте текущую дату через параметр: Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата()) и используйте &ТекущаяДата в тексте запроса.

Что делать, если разность получается отрицательной?

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

Как посчитать разность в годах для стажа сотрудника?

Используйте РазностьДат(ДатаПриема, ТекущаяДата, ТипРазностиДат.Год), затем проверьте, наступила ли годовщина приёма в текущем году: если месяц и день приёма ещё не наступили, вычтите единицу. Это даст число полных лет.

Чем отличается РАЗНОСТЬДАТ в запросе от РазностьДат в коде?

Логика подсчёта одинаковая, отличается синтаксис: в запросе единица измерения пишется без кавычек (ДЕНЬ, МЕСЯЦ, ГОД), а в коде используется перечисление ТипРазностиДат. В запросе расчёт выполняется на стороне СУБД, что быстрее при больших выборках.