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

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

Как определить количество дней между датами в 1С

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

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

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

Как 1С хранит даты и почему вычитание даёт секунды

Тип «Дата» в 1С всегда содержит и календарную дату, и время с точностью до секунды. Даже если в документе отображается только «12.03.2026», внутри хранится значение вида 12.03.2026 0:00:00. Это принципиально для расчётов: разность двух дат вычисляется как разность моментов времени.

При вычитании одной даты из другой результатом является число — количество секунд между двумя моментами. Например, разность между 15.03.2026 0:00:00 и 10.03.2026 0:00:00 равна 432000, то есть 5 суток, умноженных на 86400 секунд. Чтобы получить привычные дни, результат нужно разделить на 86400.

Из-за хранения времени возникает частая проблема: если в дате окончания стоит время 23:59:59, а не 00:00:00, деление даст дробное число. Поэтому перед расчётом даты часто приводят к началу дня функцией НачалоДня() или к концу дня функцией КонецДня(), в зависимости от логики задачи.

Способ 1: вычитание дат и деление на 86400

Самый прямой способ — арифметика с датами. Код выглядит так:

ДнейМежду = (ДатаОкончания - ДатаНачала) / 86400;

Если даты содержат произвольное время, результат может быть дробным. Чтобы получить целое число дней, применяют функцию Цел() или предварительно обрезают время:

ДнейМежду = Цел((НачалоДня(ДатаОкончания) - НачалоДня(ДатаНачала)) / 86400);

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

bsl
ДнейМежду = Цел((НачалоДня(ДатаОкончания) - НачалоДня(ДатаНачала)) / 86400);

Способ 2: функция РазностьДат

Глобальный контекст встроенного языка содержит функцию РазностьДат(), которая сразу возвращает разность в нужных единицах: секундах, минутах, часах, днях, месяцах и так далее. Синтаксис:

КоличествоДней = РазностьДат(ДатаНачала; ДатаОкончания; ДЕНЬ);

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

Важная особенность: при расчёте в днях функция учитывает время. Если между датами 4 полных суток и 23 часа, результат будет 4, а не 5. Поэтому для календарных расчётов, где важны именно даты без учёта времени, надёжнее передавать в функцию даты, приведённые к началу дня.

Способ 3: расчёт в запросе через РАЗНОСТЬДАТ

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

ВЫБРАТЬ

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

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

ИЗ

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

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

Практический приём: результаты РАЗНОСТЬДАТ удобно использовать в отборе через конструкцию ГДЕ или ИМЕЮЩИЕ, например чтобы выбрать документы старше 30 дней. Также функцию часто комбинируют с ДОБАВИТЬКДАТЕ — обратной операцией, которая прибавляет к дате заданное количество единиц времени.

Прибавление дней к дате: ДобавитьКДате и простая арифметика

Обратная задача — вычислить дату, отстоящую от исходной на заданное число дней. Простейший вариант — прибавить секунды:

ДатаОплаты = ДатаДокумента + 10 * 86400; // плюс 10 дней

Более читаемый вариант — функция ДобавитьКДате():

ДатаОплаты = ДобавитьКДате(ДатаДокумента; ДЕНЬ; 10);

Разница между подходами проявляется при работе с месяцами и годами: ДобавитьКДате корректно обрабатывает разную длину месяцев. Например, прибавление одного месяца к 31 января даст последний день февраля, а не несуществующую дату. При простом сложении секунд такой корректировки не происходит, поэтому для месяцев и лет всегда используйте ДобавитьКДате.

Сравнение способов

Вычитание и деление на 86400

Быстро и прозрачно, но требует контроля времени в датах и ручного округления

РазностьДат

Удобна для разных единиц измерения; считает полные единицы с учётом времени

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

Оптимальна для массовых расчётов по таблицам; не вызывается вне запроса

Как учитывать границы периода: включать ли первый и последний день

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

Типовые варианты постановки задачи:

  • разность между датами (сколько дней прошло): (Дата2 - Дата1) / 86400, без поправки;
  • длительность периода с включением обеих границ (например, отпуск с 1 по 14 число): разность плюс один день;
  • просрочка: разность между текущей датой и датой срока, отрицательные значения отбрасываются или трактуются как «срок не наступил».

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

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

Проверить корректность расчёта проще всего на контрольном примере с очевидным ответом: возьмите даты, разность между которыми известна заранее (например, 01.01 и 11.01 — ровно 10 дней), и прогоните через свою функцию. Затем проверьте граничные случаи: одинаковые даты, даты с разным временем, переход через конец месяца и високосный февраль.

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

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

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

Результат 10 дней

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

11 дней (лишняя единица) или дробное значение

Даты с разным временем внутри дня
Норма

Результат соответствует календарным датам

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

Результат смещается на день из-за времени

Одинаковые даты
Норма

Результат 0 (или 1, если период включает обе границы)

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

Отрицательное или непредсказуемое значение

Наиболее распространённые ошибки при расчёте дней между датами:

Типичные ошибки
01
Использование разности в секундах без деления на 86400 — результат завышен в десятки тысяч раз
02
Игнорирование времени внутри дат — дробный результат или смещение на день
03
Перепутанный порядок операндов — отрицательное количество дней
04
Прибавление месяцев через секунды вместо ДобавитьКДате — ошибка на месяцах разной длины
05
Неучтённая методика границ периода — систематическая ошибка на один день

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

Рабочие и календарные дни: ограничения простых способов

Все описанные способы считают календарные дни. Если задача требует посчитать только рабочие дни — например, для сроков исполнения заказа, — простой арифметики недостаточно: нужно учитывать выходные и праздничные дни.

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

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

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

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

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

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

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

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

Потому что результат вычитания — это секунды, а не дни. Разделите значение на 86400, чтобы получить дни. Также проверьте, не пуста ли одна из дат: пустая дата равна 01.01.0001, и разность с ней даёт миллионы дней.

Как посчитать дни между датами, включая обе границы периода?

Вычислите обычную разность дат и прибавьте единицу: ДнейВПериоде = (НачалоДня(ДатаКонца) - НачалоДня(ДатаНачала)) / 86400 + 1. Такой подход типичен для отпусков и периодов действия договоров.

Чем РазностьДат отличается от вычитания дат вручную?

РазностьДат сразу возвращает целое число в заданных единицах (дни, месяцы, годы) и считает полные единицы с учётом времени. Ручное вычитание даёт секунды и требует самостоятельного деления и округления, но прозрачнее и предсказуемее при работе с дробными значениями.

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

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

Как прибавить к дате несколько месяцев без ошибок?

Только через ДобавитьКДате(Дата; МЕСЯЦ; Количество). Функция корректно обрабатывает разную длину месяцев: прибавление месяца к 31 января даст последний день февраля. Сложение секунд такой корректировки не выполняет.

Можно ли посчитать только рабочие дни между датами?

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