Разработка и Конфигурация · 9 мин
Как посчитать разность дат в 1С
Как посчитать разность дат в 1С: функция РазностьДат, вычитание дат в секундах, расчёт в запросах и на форме. Примеры кода, ошибки и проверка результата.
Задача вычислить разность между двумя датами встречается в 1С постоянно: расчёт стажа сотрудника, срока хранения товара, просрочки по договору, длительности производственной операции. В зависимости от того, где выполняется расчёт — в коде модуля, в запросе или в формуле СКД — применяются разные инструменты, и у каждого есть свои ограничения.
Главное, что нужно понять сразу: встроенный язык 1С при вычитании дат возвращает результат в секундах, а не в днях. Это частая причина ошибок у начинающих разработчиков, которые ожидают получить количество дней и получают огромное число вроде 864000. Для расчёта в календарных единицах — месяцах, кварталах, годах — существует отдельная функция РазностьДат.
Ниже разобраны все рабочие способы: вычитание дат оператором, функция РазностьДат, расчёт в запросе, особенности високосных лет и граничных дат, а также типичные ошибки и способы проверить результат.
Вычитание дат оператором: разность в секундах
Самый простой способ — обычное вычитание. Если из одного значения типа Дата вычесть другое, результатом будет число секунд между ними. Это удобно, когда нужно измерить длительность операции с точностью до секунды, например время выполнения обработки.
ДатаНачала = '20260301100000';
ДатаОкончания = '20260305120000';
РазностьСекунд = ДатаОкончания - ДатаНачала; // 352800 секунд
РазностьДней = РазностьСекунд / 86400; // 4,083 дня
Чтобы получить целое количество дней, делите результат на 86400 (60 × 60 × 24) и при необходимости округляйте через Цел(). Учтите: если даты содержат время, результат почти никогда не будет целым числом дней. Для расчёта по календарным дням без учёта времени предварительно отсеките время функцией НачалоДня.
РазностьДней = Цел((НачалоДня(ДатаОкончания) - НачалоДня(ДатаНачала)) / 86400);Порядок операндов имеет значение: если вычесть большую дату из меньшей, получите отрицательное число. Перед расчётом полезно проверить, какая дата больше, особенно если данные приходят из пользовательского ввода или загрузки из файла.
Функция РазностьДат: месяцы, кварталы и годы
Для календарных периодов простое деление на секунды не подходит: месяцы имеют разную длину, а годы бывают високосными. Встроенная функция РазностьДат решает эту задачу.
// Синтаксис: РазностьДат(Дата1, Дата2, ТипРазности)
Месяцев = РазностьДат('20260115', '20260720', ТипРазностиДат.Месяц); // 6
Дней = РазностьДат('20260115', '20260720', ТипРазностиДат.День);
Параметр ТипРазности принимает значения перечисления ТипРазностиДат: Секунда, Минута, Час, День, Месяц, Квартал, Год. Важная особенность: функция считает количество полных границ периода между датами. Между 31 января и 1 февраля разность в месяцах равна 1, хотя прошёл всего один день. Это нужно учитывать при расчёте стажа или сроков оплаты.
Если нужна разность в днях без учёта времени, комбинируйте функцию с НачалоДня — иначе разница в одну секунду между датами разных дней даст результат 1 день, что обычно корректно, но при сравнении дат внутри одного дня даст 0 даже при разнице в 23 часа.
Расчёт разности дат в запросе
В языке запросов 1С есть собственная функция РАЗНОСТЬДАТ, которая работает аналогично, но с другим синтаксисом: единица измерения указывается третьим параметром без кавычек.
ВЫБРАТЬ
Заказ.Ссылка,
РАЗНОСТЬДАТ(Заказ.Дата, &ТекущаяДата, ДЕНЬ) КАК ДнейСЗаказа,
РАЗНОСТЬДАТ(Заказ.ДатаОтгрузки, Заказ.ДатаОплаты, ДЕНЬ) КАК ДнейОтсрочки
ИЗ
Документ.ЗаказПокупателя КАК Заказ
Допустимые единицы: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Функция удобна для отборов — например, выбрать все документы с просрочкой более 30 дней, поместив условие РАЗНОСТЬДАТ в секцию ГДЕ или ИМЕЮЩИЕ.
- 1Добавьте в выборку РАЗНОСТЬДАТ(ДатаДокумента, &ТекущаяДата, ДЕНЬ) КАК ДнейПросрочки
- 2Передайте параметр &ТекущаяДата через УстановитьПараметр — функция ТекущаяДата() в запросе недоступна
- 3Добавьте условие ГДЕ РАЗНОСТЬДАТ(...) > 30 для отбора просроченных
- 4Проверьте результат на документе с известными датами
Обратите внимание: в запросе нельзя вызвать ТекущаяДата() напрямую. Дату сравнения передавайте параметром из кода. Также помните, что пустая дата (01.01.0001) в расчёте даст огромное значение — фильтруйте записи с незаполненными датами через ЕСТЬ NULL или сравнение с пустой датой.
Разность дат в СКД и отчётах
В системе компоновки данных разность дат обычно считается либо в исходном запросе набора данных функцией РАЗНОСТЬДАТ, либо в выражении вычисляемого поля. Первый вариант предпочтительнее: расчёт выполняется на уровне СУБД и не замедляет формирование отчёта.
Если разность нужна в ресурсе отчёта с группировками, добавьте вычисляемое поле и настройте агрегирование — например, среднюю длительность обработки заказа по менеджерам через функцию Среднее(). Учтите, что агрегировать сами даты нельзя, агрегируется уже посчитанная числовая разность.
Где считать разность дат
Подходит для секунд и точной длительности; требует ручного пересчёта в дни
Подходит для календарных периодов в модуле; не работает внутри запроса
Оптимально для отборов и отчётов; требует передачи текущей даты параметром
Подходит для отчётов без изменения запроса; медленнее при больших объёмах
Крайние случаи: время, високосные годы и пустые даты
Большинство ошибок в расчётах с датами связано не с самими функциями, а с данными. Пустая дата 01.01.0001, участвующая в вычитании, даст разность в сотни тысяч дней и исказит отчёт. Всегда проверяйте заполненность дат через ЗначениеЗаполнено() до расчёта.
Вторая группа проблем — состав даты. Если документ хранит дату со временем, разность между «сегодня 09:00» и «завтра 18:00» составит 1 день по функции РазностьДат с типом День, но 33 часа по точному вычитанию. Определитесь заранее, что для вашей задачи является корректным результатом, и приводите даты к началу или концу дня.
Как проверить результат расчёта
1 день или 86400 секунд
0 дней или отрицательное значение
1 месяц (граница пересечена)
Ожидание 0 месяцев как «полных»
Ветка обработки отсутствующего значения
Результат в сотни тысяч дней
Осознанное поведение с проверкой порядка дат
Молчаливый минус в отчёте
Високосный год влияет на расчёты через февраль: между 28.02 и 01.03 високосного года проходит два дня, а не один. Функции 1С учитывают это автоматически, но если вы пишете собственный пересчёт дней в месяцах «вручную», такие места нужно тестировать отдельно.
Типичные ошибки и как их избежать
Самая распространённая ошибка — забыть, что вычитание даёт секунды, и вывести в отчёт число вроде 2592000 вместо 30 дней. Вторая по частоте — использование РазностьДат с типом Месяц для расчёта «полных» месяцев стажа, из-за чего сотруднику, принятому 31 января, 1 февраля уже «насчитается» месяц.
Ещё одна ловушка — хранение разности дат в реквизите типа Дата. Разность — это число (длительность), а не дата. Попытка присвоить результат вычитания реквизиту с типом Дата приведёт к ошибке преобразования или бессмысленному значению. Используйте числовой реквизит с подходящей точностью.
Что важно запомнить
Вычитание дат даёт секунды, РазностьДат — календарные периоды по границам, РАЗНОСТЬДАТ работает в запросах и требует параметр для текущей даты. Всегда проверяйте заполненность дат и порядок операндов.
Частые вопросы
Как получить разность дат в днях без учёта времени?
Приведите обе даты к началу дня и разделите разность в секундах на 86400: Цел((НачалоДня(Дата2) - НачалоДня(Дата1)) / 86400). Так разница во времени не повлияет на результат.
Почему РазностьДат между 31 января и 1 февраля даёт 1 месяц?
Функция считает количество пересечённых границ периодов, а не полностью протёкшие месяцы. Между этими датами граница месяца пересечена один раз. Для расчёта полных месяцев добавьте проверку, наступил ли день месяца конечной даты.
Можно ли использовать ТекущаяДата() внутри запроса?
Нет, в языке запросов эта функция недоступна. Передайте текущую дату через параметр: Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата()) и используйте &ТекущаяДата в тексте запроса.
Что делать, если разность получается отрицательной?
Отрицательный результат означает, что первая дата позже второй. Либо поменяйте операнды местами, либо перед расчётом сравните даты и обработайте ситуацию явно — например, выведите предупреждение о некорректных данных.
Как посчитать разность в годах для стажа сотрудника?
Используйте РазностьДат(ДатаПриема, ТекущаяДата, ТипРазностиДат.Год), затем проверьте, наступила ли годовщина приёма в текущем году: если месяц и день приёма ещё не наступили, вычтите единицу. Это даст число полных лет.
Чем отличается РАЗНОСТЬДАТ в запросе от РазностьДат в коде?
Логика подсчёта одинаковая, отличается синтаксис: в запросе единица измерения пишется без кавычек (ДЕНЬ, МЕСЯЦ, ГОД), а в коде используется перечисление ТипРазностиДат. В запросе расчёт выполняется на стороне СУБД, что быстрее при больших выборках.