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

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

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

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

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

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

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

Тип «Дата» в 1С хранит значение с точностью до секунды. Когда вы пишете выражение ДатаОкончания - ДатаНачала, платформа возвращает число — количество секунд между двумя моментами времени. Это удобно для точных измерений, но неожиданно для тех, кто ждёт сразу дни.

Чтобы получить количество дней, разделите результат на 86400 — число секунд в сутки (60 × 60 × 24):

КоличествоДней = (ДатаОкончания - ДатаНачала) / 86400;

Обратите внимание: если даты содержат время, результат будет дробным. Например, разница между 10:00 одного дня и 18:00 следующего даст 1,33 дня. Для целочисленного результата применяйте функции округления (Цел, Окр) или предварительно отсекайте время функцией НачалоДня.

Получаем целые дни: НачалоДня и округление

Чтобы избежать дробных значений, приведите обе даты к началу суток перед вычитанием:

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

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

Если время отсекать нельзя, используйте округление вниз: Цел((ДатаОкончания - ДатаНачала) / 86400). Помните, что Цел просто отбрасывает дробную часть, а Окр округляет по математическим правилам — выбирайте в зависимости от логики учёта.

Функция РазностьДат в запросах

В языке запросов 1С есть встроенная функция РАЗНОСТЬДАТ, которая возвращает разность в указанных единицах: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД:

ВЫБРАТЬ

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

ИЗ

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

Функция удобна тем, что считает разность именно в календарных единицах: при типе МЕСЯЦ или ГОД учитывается не количество секунд, а смена календарного месяца или года. Для типа ДЕНЬ результат эквивалентен разности в секундах, делённой на 86400, с отбрасыванием дробной части.

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

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

В модулях на встроенном языке доступна одноимённая функция глобального контекста:

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

Третий параметр — значение перечисления СпособВычисленияРазностиДат (Секунда, Минута, Час, День, Месяц, Квартал, Год). Функция избавляет от ручного деления на 86400 и делает код читаемее, особенно когда нужны месяцы или годы — там простое деление на секунды не работает из-за разной длины месяцев.

Важное отличие от вычитания: РазностьДат считает по календарным границам. Разность между 31 января и 1 февраля в единицах МЕСЯЦ равна 1, хотя прошли одни сутки. Для расчёта возраста или стажа такое поведение может дать погрешность — проверяйте логику на граничных датах.

Способы вычислить дни между датами

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

Простой и быстрый способ для календарных дней. Требует контроля времени в датах и округления.

РазностьДат во встроенном языке

Читаемый код, поддержка месяцев и лет. Подходит для модулей, но считает по календарным границам.

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

Оптимально для отчётов и выборок: расчёт выполняется на сервере СУБД без перебора данных в коде.

Производственный календарь

Единственный корректный способ посчитать рабочие дни с учётом праздников и переносов.

Считаем рабочие дни через производственный календарь

Разность дат всегда даёт календарные дни, включая выходные и праздники. Если нужно посчитать рабочие дни — например, для сроков исполнения договора или табеля — потребуется производственный календарь. В типовых конфигурациях (1С:ЗУП, 1С:Бухгалтерия) есть регистр сведений «Данные производственного календаря», где каждому дню соответствует вид дня: рабочий, выходной, праздничный и так далее.

Общий подход такой: выбираете запросом все даты из календаря в нужном диапазоне с видом дня «рабочий» (или «предпраздничный», если он считается рабочим в вашей логике) и берёте их количество:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| КОЛИЧЕСТВО(Календарь.Дата) КАК РабочихДней

|ИЗ

| РегистрСведений.ДанныеПроизводственногоКалендаря КАК Календарь

|ГДЕ

| Календарь.Дата МЕЖДУ &Начало И &Конец

| И Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)";

Имена регистров и перечислений зависят от конфигурации — уточните структуру метаданных в своей базе. В самописных решениях часто заводят собственный регистр календаря или простой справочник выходных.

Типичные сценарии на практике

Просрочка оплаты или дебиторской задолженности

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

Срок годности и хранения

Для партий товара со сроком годности вычисляют остаток дней до истечения: РАЗНОСТЬДАТ(&ТекущаяДата, Партия.СрокГодности, ДЕНЬ). Значения вблизи нуля позволяют строить отчёты «истекает в ближайшие N дней», отбирая диапазон условием МЕЖДУ 0 И &Порог.

Стаж и возраст

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

Порядок действий для расчёта дней
  1. 1
    Определите, какие дни нужны: календарные или рабочие
  2. 2
    Для календарных — используйте (НачалоДня(Дата2) - НачалоДня(Дата1)) / 86400 или РазностьДат
  3. 3
    Для рабочих — постройте запрос к производственному календарю
  4. 4
    Проверьте порядок аргументов: перепутанные даты дают отрицательный результат
  5. 5
    Протестируйте на граничных случаях: одинаковые даты, переход через месяц и год

Частые ошибки и как их избежать

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

Отдельная группа проблем — пустые даты. Незаполненная дата в 1С равна 01.01.0001, и разность с ней даст огромное число дней. Перед расчётом проверяйте заполненность: Если ЗначениеЗаполнено(ДатаОкончания) Тогда .... В запросах используйте условие Дата <> ДАТАВРЕМЯ(1,1,1).

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

Проверка результата

После реализации расчёта проверьте его на контрольных примерах. Разность между 1 марта и 10 марта должна быть 9 дней. Одинаковые даты должны давать 0. Переход через границу года — например, с 30 декабря по 5 января — должен дать 6 дней, что легко проверяет корректность работы со сменой года.

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

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

Как проверить корректность расчёта

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

Результат равен 0

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

Результат дробный или отличен от нуля — в датах осталось время

Разность 1 марта и 10 марта
Норма

Результат равен 9

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

Значение кратно 86400 — забыто деление на секунды

Пустая дата окончания
Норма

Расчёт пропускается или выдаёт осмысленное сообщение

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

В результате огромное число дней

Неделя с праздником для рабочих дней
Норма

Число совпадает с ручным подсчётом по календарю

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

Праздник засчитан рабочим — проверьте вид дня в запросе

Часто задаваемые вопросы

Итог

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

Разность дат в 1С — это секунды: делите на 86400 или используйте РазностьДат. Отсекайте время через НачалоДня, проверяйте пустые даты, а рабочие дни считайте только по производственному календарю.

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

Потому что 1С возвращает разность в секундах. Разделите результат на 86400, чтобы получить дни, либо используйте функцию РазностьДат с параметром День.

Как получить целое число дней без дробной части?

Приведите обе даты к началу суток функцией НачалоДня перед вычитанием. Альтернатива — обернуть результат в Цел() или Окр(), в зависимости от требуемого правила округления.

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

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

Что вернёт РазностьДат, если даты перепутаны местами?

Отрицательное число. Это можно использовать как признак просрочки: если дата оплаты передать первым аргументом, а текущую дату — вторым, отрицательный результат покажет, что срок прошёл.

Как вычислить разность в месяцах или годах?

Делением на секунды это не решить из-за разной длины месяцев. Используйте РазностьДат с типом МЕСЯЦ или ГОД, но помните: функция считает смену календарных границ, поэтому для точного стажа или возраста нужна дополнительная корректировка по дню и месяцу.

Можно ли вычислить дни между датами без программирования?

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