Разработка и Конфигурация · 10 мин
Как посчитать количество дней между датами в 1С
Способы вычислить количество дней между двумя датами в 1С: функция РазностьДат, запросы, календарные и рабочие дни, типовые ошибки и примеры кода.
Задача вычислить количество дней между двумя датами возникает в 1С постоянно: при расчёте стажа, сроков договоров, просрочки платежей, длительности отпуска или отработанного времени. Встроенный язык платформы даёт для этого несколько инструментов, и выбор зависит от того, где выполняется расчёт — в коде модуля, в запросе или в выражении СКД.
Главный инструмент — функция РазностьДат(), которая возвращает разницу между датами в заданной единице измерения. Дополнительно разность можно получить простым вычитанием дат, через язык запросов функцией РАЗНОСТЬДАТ, а для рабочих дней — через производственные календари. Каждый способ имеет свои ограничения, о которых важно знать до внедрения.
Ниже разобраны рабочие примеры кода, особенности учёта високосных лет и времени, расчёт рабочих дней по календарю и типичные ошибки, из-за которых результат оказывается на один день больше или меньше ожидаемого.
Функция РазностьДат — основной способ в коде
Функция РазностьДат() доступна в глобальном контексте встроенного языка и работает на тонком, толстом и веб-клиенте, а также на сервере. Синтаксис прост: первые два параметра — даты, третий — единица измерения разности из системного перечисления ТипРазностиДат.
ДатаНачала = '20260115';
ДатаОкончания = '20260320';
КоличествоДней = РазностьДат(ДатаНачала, ДатаОкончания, ТипРазностиДат.День);
// Результат: 65
Помимо дней, функция умеет возвращать разность в секундах, минутах, часах, месяцах, кварталах и годах. Это удобно, когда нужно, например, определить возраст сотрудника в годах или длительность операции в минутах — меняется только третий параметр.
Важная особенность: если даты содержат время, функция учитывает его. Разница между 15.01.2026 23:00:00 и 16.01.2026 01:00:00 составит 0 дней, потому что полные сутки ещё не прошли. Если нужен расчёт по календарным датам без учёта времени, предварительно отсеките время функцией НачалоДня().
Простое вычитание дат и его ограничения
В 1С допустима операция вычитания одной даты из другой: Разность = Дата2 - Дата1;. Результатом будет число — количество секунд между датами. Чтобы получить дни, результат делят на 86400 (количество секунд в сутках).
РазностьВСекундах = ДатаОкончания - ДатаНачала;
КоличествоДней = Цел(РазностьВСекундах / 86400);
Способ рабочий, но менее читаемый и более подвержен ошибкам: легко забыть про округление, время в составе даты или неверно выбрать функцию округления (Цел отбрасывает дробную часть, а для «полных суток» иногда нужно Окр). В новом коде предпочтительнее РазностьДат() — она явно выражает намерение и не требует ручной арифметики с секундами.
Вычитание оправдано, когда нужна именно разность в секундах — например, для замера длительности выполнения операции или при работе с Unix-временем при обмене данными с внешними системами.
Расчёт разности дат в запросе
Когда даты хранятся в базе данных и расчёт нужен для выборки, разумно выполнить его на стороне запроса — это быстрее, чем перебирать результат в цикле. В языке запросов для этого служит функция РАЗНОСТЬДАТ.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Договоры.Ссылка КАК Договор,
| РАЗНОСТЬДАТ(Договоры.ДатаНачала, Договоры.ДатаОкончания, ДЕНЬ) КАК СрокДней
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК Договоры";
Третий параметр функции принимает значения СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Обратите внимание: в запросе имена пишутся без префикса «ТипРазностиДат», в отличие от кода встроенного языка.
Практический приём: если нужна просрочка оплаты относительно текущей даты, передайте текущую дату параметром запроса, а не вычисляйте её в цикле. Так запрос останется декларативным и быстрым:
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
// В тексте запроса:
// РАЗНОСТЬДАТ(Реализация.ДатаОплаты, &ТекущаяДата, ДЕНЬ) КАК ДнейПросрочки
КоличествоДней = РазностьДат(НачалоДня(ДатаНачала), НачалоДня(ДатаОкончания), ТипРазностиДат.День);Как посчитать рабочие дни по производственному календарю
Календарная разность не подходит, когда нужно число рабочих дней: для расчёта отпускных, сроков выполнения заказов или регламентных дат ответа на обращения. Здесь используется регистр сведений «Данные производственного календаря» (в типовых конфигурациях на БСП) или аналогичный механизм конкретной конфигурации.
Логика расчёта: запросом выбираются все даты из календаря в заданном диапазоне, у которых вид дня — рабочий (рабочий или предпраздничный, в зависимости от методики), и считается их количество. Праздничные и выходные дни исключаются условием отбора.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(Календарь.Дата) КАК РабочихДней
|ИЗ
| РегистрСведений.ДанныеПроизводственногоКалендаря КАК Календарь
|ГДЕ
| Календарь.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
| И Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)";
В конфигурациях на базе Библиотеки стандартных подсистем есть готовые функции модуля КалендарныеГрафики, позволяющие получить разность в рабочих днях по графику работы. Перед написанием собственного запроса проверьте, нет ли готовой функции в вашей конфигурации — это сэкономит время и учтёт особенности заполнения календарей.
Критично следить за актуальностью производственного календаря: если он не заполнен на нужный период, запрос вернёт ноль или заниженное значение, и расчёт сроков окажется неверным. Перед расчётами на будущие периоды убедитесь, что календарь заполнен.
Нюансы: включение границ, время и пустые даты
Самый частый спор при постановке задачи — включать ли дату окончания в расчёт. РазностьДат не включает её: между 1 и 10 марта — 9 дней. Если по бизнес-правилу период считается включительно (например, отпуск с 1 по 10 марта — это 10 календарных дней), добавьте к результату единицу и зафиксируйте это в комментарии к коду.
Пустая дата ('00010101') — источник неожиданных результатов. Разность между пустой и реальной датой даст огромное число, которое затем попадёт в отчёты. Перед расчётом проверяйте даты на заполненность через ЗначениеЗаполнено() и решайте, что делать: пропускать строку, считать от текущей даты или выдавать предупреждение.
Отдельная ситуация — дата окончания раньше даты начала. Функция вернёт отрицательное число, что для многих отчётов неприемлемо. Добавьте проверку порядка дат и либо меняйте их местами, либо фиксируйте ошибку в данных.
Проверка результата и отладка
Прежде чем внедрять расчёт в рабочий код, проверьте его на контрольных примерах. Удобные тестовые пары: разность даты с самой собой (должна быть 0), соседние даты (1), период через високосный февраль, период с датами, содержащими время.
Быструю проверку удобно выполнять в консоли кода (внешней обработке «Консоль кода» или аналогичной): введите выражение с конкретными датами и сравните результат с ручным подсчётом по календарю. Для запросов используйте консоль запросов с теми же параметрами.
Как проверить результат
Возвращается 0
Возвращается 1 или -1 — вероятно, разное время в датах
9 дней без включения границы или 10 с добавленной единицей — по методике
Значение не совпадает ни с одним вариантом — проверяйте время и порядок дат
5 рабочих дней
7 дней — считается календарная разность, 0 — календарь не заполнен
Выбор способа под задачу
Для разового расчёта в модуле объекта или формы достаточно РазностьДат() — это самый читаемый вариант. Для массовых выборок из базы — функция РАЗНОСТЬДАТ в запросе, она выполняется на сервере СУБД и не требует обхода данных. Для выражений в СКД и динамических списках доступен тот же синтаксис языка запросов.
Если расчёт завязан на рабочее время, сроки реакции или кадровые периоды, используйте производственный календарь и готовые функции библиотеки, а не самодельные переборы дат в цикле — цикл по дням с проверкой каждого дня работает заметно медленнее и сложнее в сопровождении.
Сравнение вариантов
Универсальный выбор для кода модулей; требует контроля времени в датах
Даёт секунды; подходит для замеров длительности, для дней нужно деление и округление
Оптимально для выборок из базы; не работает вне запроса
Единственный корректный способ для рабочих дней; требует заполненного календаря
Частые вопросы
Как посчитать количество дней между датами включая обе даты?
Вызовите РазностьДат(ДатаНачала, ДатаОкончания, ТипРазностиДат.День) и прибавьте 1 к результату. Функция по умолчанию не включает дату окончания, поэтому период с 1 по 10 марта даст 9, а с добавленной единицей — 10 календарных дней.
Почему РазностьДат возвращает на один день меньше, чем ожидалось?
Чаще всего причина во времени в составе дат: функция считает полные сутки. Если дата начала содержит время 15:00, а окончания — 10:00, сутки неполные. Примените НачалоДня() к обеим датам перед вычислением.
Как посчитать разность в месяцах или годах?
Используйте ту же функцию с другим типом разности: ТипРазностиДат.Месяц или ТипРазностиДат.Год. Учтите, что считаются полные месяцы и годы — с 20 января по 10 февраля полный месяц ещё не прошёл, и результат будет 0.
Можно ли посчитать дни между датами без программирования?
Да, если данные выводятся в отчёт на СКД: добавьте вычисляемое поле с выражением РАЗНОСТЬДАТ(ДатаНачала, ДатаОкончания, ДЕНЬ) на языке запросов. Для разовой проверки подойдёт консоль кода или консоль запросов.
Что делать, если дата окончания может быть раньше даты начала?
Добавьте проверку: если ДатаОкончания < ДатаНачала, либо поменяйте даты местами, либо сообщите об ошибке в данных. Без проверки функция вернёт отрицательное число, что может исказить итоги отчёта.
Как учесть часовые пояса при расчёте от текущей даты?
Используйте ТекущаяДатаСеанса() вместо ТекущаяДата() — она возвращает дату с учётом часового пояса сеанса и корректно работает при распределённой работе пользователей в разных регионах.
Что важно запомнить
Для кода используйте РазностьДат с типом День, для запросов — РАЗНОСТЬДАТ, для рабочих дней — производственный календарь. Всегда отсекайте время через НачалоДня, проверяйте даты на пустоту и порядок, а включение граничной даты фиксируйте в методике расчёта.