Разработка и Конфигурация · 11 мин
Как узнать количество дней между датами в 1С
Как посчитать количество дней между датами в 1С: разность дат в запросе, функции языка, календарные и рабочие дни, типовые ошибки и примеры кода.
Подсчёт количества дней между двумя датами — одна из самых частых задач при работе с 1С: расчёт просрочки по договору, стажа сотрудника, срока хранения товара, длительности отпуска или отсрочки платежа. В зависимости от контекста задача решается по-разному: в запросе, встроенным языком, через календарные графики или типовые механизмы конфигурации.
Важно сразу определить, что именно нужно посчитать: календарные дни, рабочие дни по производственному календарю или разность с учётом времени. От этого зависит выбор инструмента и точность результата. Ошибка в постановке задачи — самая частая причина неверных расчётов, например когда просрочка считается в календарных днях, а по договору положены рабочие.
Ниже разобраны основные способы: функция РАЗНОСТЬДАТ в запросах, вычитание дат встроенным языком, работа с календарями для рабочих дней, а также типичные ошибки и способы проверки результата.
Что нужно определить перед расчётом
Прежде чем писать код, ответьте на три вопроса. Первый — какие дни нужны: календарные (включая выходные и праздники) или только рабочие. Второй — где выполняется расчёт: в запросе при построении отчёта, в модуле объекта при проведении документа или в форме при интерактивном вводе. Третий — учитывается ли время: даты в 1С всегда содержат время с точностью до секунды, и это влияет на результат.
Отдельный момент — границы периода. Вопрос «включать ли последний день» звучит просто, но именно из-за него расчёты «на один день» расходятся с ожиданиями пользователей. Например, с 1 по 10 марта — это 9 дней разности или 10 дней периода «включительно». Договоритесь о правиле до реализации и зафиксируйте его в комментарии к коду.
Расчёт разности дат в запросе: РАЗНОСТЬДАТ
Основной инструмент для расчётов в запросах — функция РАЗНОСТЬДАТ. Она принимает три параметра: начальную дату, конечную дату и единицу измерения (СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, ГОД). Функция возвращает количество полных единиц между датами.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, ДЕНЬ) КАК КоличествоДней";
Запрос.УстановитьПараметр("ДатаНачала", '20260301');
Запрос.УстановитьПараметр("ДатаОкончания", '20260315');
Результат = Запрос.Выполнить().Выгрузить();
КоличествоДней = Результат[0].КоличествоДней; // 14
Обратите внимание: если поменять даты местами, результат будет отрицательным. Это удобно для определения просрочки — отрицательное значение сразу показывает, что срок ещё не наступил. Если нужен модуль, оберните вычисление в проверку условия или используйте конструкцию ВЫБОР в запросе.
РАЗНОСТЬДАТ работает и в динамических списках, и в СКД, что позволяет выводить количество дней прямо в отчётах без дополнительной обработки данных. Например, колонку «Дней просрочки» в отчёте по дебиторской задолженности удобно считать именно на уровне запроса.
РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, ДЕНЬ) КАК КоличествоДнейРасчёт встроенным языком: вычитание дат и добавление дней
Вне запроса разность считается простым вычитанием. Результат вычитания двух дат — число секунд, поэтому для получения дней его делят на 86400 (60 × 60 × 24). Дробная часть появляется, если у дат разное время.
Дата1 = '20260301000000';
Дата2 = '20260315000000';
КоличествоДней = (Дата2 - Дата1) / 86400; // 14
// Если время у дат разное, результат будет дробным:
Дата3 = '20260315120000';
ДробныйРезультат = (Дата3 - Дата1) / 86400; // 14,5
Для обратной задачи — получить дату через заданное число дней — просто прибавьте к дате нужное количество секунд: НоваяДата = ИсходнаяДата + 10 * 86400;. Также полезны функции НачалоДня(), КонецДня() и НачалоМесяца(): они помогают отбросить время перед расчётом и избежать дробных результатов.
Если нужно посчитать разность в месяцах или годах встроенным языком, используйте функции Месяц() и Год() с корректировкой на неполные периоды, либо вынесите расчёт в запрос — РАЗНОСТЬДАТ с единицей МЕСЯЦ или ГОД сделает это корректнее, учитывая разную длину месяцев.
Как посчитать рабочие дни по производственному календарю
Разность дат даёт только календарные дни. Если по условиям задачи нужны рабочие дни — например, для расчёта отсрочки платежа «10 рабочих дней» или срока ответа на претензию — потребуется производственный календарь. В типовых конфигурациях для этого существуют регистры сведений с данными календарных графиков (например, «Данные производственного календаря» или «Календарные графики» в зависимости от конфигурации).
Общий подход такой: запросом выбираются все даты между начальной и конечной из регистра календаря с отбором по виду дня (рабочий), и считается их количество. В типовых решениях часто есть готовые функции общих модулей — например, в библиотеке стандартных подсистем есть механизмы работы с календарными графиками, которые умеют считать рабочие дни и прибавлять их к дате.
// Пример логики запроса по регистру календаря:
// ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ РегистрСведений.ДанныеПроизводственногоКалендаря
// ГДЕ Дата МЕЖДУ &Начало И &Конец И ВидДня = &РабочийДень
Перед внедрением такого расчёта убедитесь, что производственный календарь в базе заполнен на нужный период. Если календарь не заполнен, запрос вернёт ноль или заниженное значение, и ошибка может остаться незамеченной до реальных расчётов с контрагентами.
Как проверить результат и отладить расчёт
Самый быстрый способ проверить расчёт вручную — консоль запросов или консоль кода (внешняя обработка, широко используемая разработчиками). Введите тестовые даты, выполните код и сверьте результат с ручным подсчётом по календарю. Для граничных случаев проверяйте переход через месяц, через год и високосный февраль.
Полезный приём — тестирование на «единичном» периоде: разность между датой и ей же самой должна давать 0, разность соседних дат — 1. Если уже на таких примерах результат неверен, проблема в логике, а не в данных. Также проверяйте поведение при пустых датах: пустая дата 01.01.0001 даст огромную разность и может «утянуть» итоги отчёта.
Как проверить результат
Результат равен 0
Любое другое число — ошибка в формуле
Результат равен 1
Дробное значение — не отброшено время
Пустые даты отфильтрованы условием
Огромные значения в итогах отчёта
Число близко к календарным дням минус выходные и праздники
Ноль или завышенное значение — календарь не заполнен
Типичные ошибки при расчёте дней между датами
Большинство проблем с расчётом дней связано не со сложностью задачи, а с невниманием к деталям платформы. Разберём самые частые ошибки и их последствия.
Отдельно стоит сказать про округление. Если вы всё же работаете с дробной разностью, выбирайте правило округления осознанно: Цел() отбрасывает дробную часть, Окр() округляет по правилам, а для «любой неполный день считается полным» нужен отдельный алгоритм с проверкой остатка. Формулировка в договоре или регламенте должна однозначно определять это правило.
Выбор способа под конкретную задачу
Каждый из способов имеет свою область применения, и выбирать стоит исходя из контекста, а не привычки.
Сравнение вариантов
Подходит для отчётов, динамических списков и выборок. Не работает вне запроса
Подходит для расчётов в модулях и формах. Требует деления на 86400 и контроля времени
Единственный корректный способ для рабочих дней. Требует заполненного календаря и более сложного запроса
Готовые механизмы библиотек для календарных графиков. Зависят от состава конфигурации
Для отчётов почти всегда выгоднее РАЗНОСТЬДАТ: расчёт выполняется на уровне СУБД, не нужно перебирать строки в коде, а результат сразу доступен как поле. Для интерактивных расчётов в форме (например, пользователь выбрал две даты и сразу видит число дней) достаточно вычитания с делением. Для юридически значимых расчётов — пени, неустойки, сроки ответа — используйте только тот способ, который соответствует формулировке договора, и зафиксируйте алгоритм в комментариях.
Что важно запомнить
Календарные дни считаются через РАЗНОСТЬДАТ в запросе или вычитанием дат с делением на 86400. Время в датах влияет на результат — приводите даты к началу дня. Рабочие дни считаются только по заполненному производственному календарю. Всегда проверяйте граничные случаи: пустые даты, одинаковые даты и правило включения последнего дня.
Частые вопросы
Как посчитать количество дней между датами без запроса?
Вычтите одну дату из другой и разделите результат на 86400 — число секунд в сутках. Например: (ДатаОкончания - ДатаНачала) / 86400. Если время в датах не важно, предварительно примените НачалоДня() к обеим датам, чтобы получить целое число.
Почему РАЗНОСТЬДАТ возвращает отрицательное число?
Функция вычитает первую дату из второй. Если начальная дата позже конечной, результат будет отрицательным. Это удобно для определения просрочки: отрицательное значение означает, что срок ещё не наступил. При необходимости добавьте проверку условия или конструкцию ВЫБОР.
Как учесть последний день периода в расчёте?
РАЗНОСТЬДАТ и вычитание дат считают разность между моментами, поэтому период с 1 по 10 марта даст 9 дней. Если по правилам нужно включить последний день, добавьте к результату единицу или используйте для конечной даты КонецДня() с соответствующей корректировкой логики. Правило должно быть согласовано с постановкой задачи.
Что делать, если в данных встречаются пустые даты?
Пустая дата в 1С — это 01.01.0001, и разность с ней даст огромное число. В запросе отфильтруйте такие записи условием Дата <> ДАТАВРЕМЯ(1,1,1) или обработайте их через ЕСТЬNULL и ВЫБОР. В коде проверяйте дату функцией ЗначениеЗаполнено() перед расчётом.
Как посчитать рабочие дни, если в конфигурации нет производственного календаря?
Без заполненного календаря корректный расчёт рабочих дней невозможен — выходные и праздники нельзя определить арифметически. Создайте и заполните календарный график (в типовых решениях есть соответствующие механизмы и обработки заполнения), либо используйте приближённый расчёт только для черновых оценок с явной оговоркой о погрешности.
Можно ли посчитать разность в месяцах или годах?
Да, в запросе используйте РАЗНОСТЬДАТ с единицей МЕСЯЦ или ГОД — функция учитывает разную длину месяцев и високосные годы. Во встроенном языке надёжного простого деления нет, поэтому для месяцев и лет расчёт лучше выносить в запрос или комбинировать функции Год() и Месяц() с корректировкой на неполный период.