Разработка и Конфигурация · 9 мин
Как в 1С получить разность дат
Разбор способов получить разность дат в 1С: секунды через вычитание, РазностьДат, РАЗНОСТЬДАТ в запросах, расчёт в днях и месяцах, типичные ошибки.
Разность дат — одна из самых частых задач при разработке и доработке конфигураций 1С: расчёт стажа, сроков оплаты, просрочки задолженности, длительности отпуска. Встроенный язык платформы предлагает несколько инструментов, и выбор зависит от того, где выполняется расчёт — в коде модуля или в запросе — и в каких единицах нужен результат: секундах, днях, месяцах или годах.
Главная особенность, которую нужно понимать с самого начала: в 1С дата хранится с точностью до секунды, и простое вычитание двух дат даёт результат именно в секундах, а не в днях. Это источник большинства ошибок у начинающих разработчиков. Ниже разобраны все рабочие способы с примерами кода, ограничениями и проверкой результата.
Как 1С хранит даты и почему вычитание даёт секунды
Тип «Дата» в платформе 1С содержит и календарную дату, и время с точностью до секунды. Когда вы пишете выражение ДатаОкончания - ДатаНачала, платформа возвращает число — количество секунд между двумя моментами. Никакой автоматической конвертации в дни не происходит.
Чтобы получить количество дней из секунд, результат делят на число секунд в сутках — 86400 (60 × 60 × 24). Пример:
РазностьСекунд = ДатаОкончания - ДатаНачала;
КоличествоДней = Цел(РазностьСекунд / 86400);Обратите внимание на функцию Цел(): если даты содержат время, деление даст дробное число. Отбрасывание дробной части даёт число полных суток между датами. Если нужен округлённый результат — используйте Окр(), но осознанно: для расчёта просрочки округление вверх может завысить начисления.
Функция РазностьДат из Библиотеки стандартных подсистем
В типовых конфигурациях на базе БСП (1С:Бухгалтерия, Управление торговлей, ERP, Зарплата и управление персоналом) есть готовая функция ОбщегоНазначения.РазностьДат() либо аналогичные функции в модуле КалендарныеГрафики и связанных подсистемах. Она возвращает разность в указанной единице измерения.
Точное имя и состав параметров зависят от версии библиотеки, поэтому перед использованием откройте конфигуратор и найдите функцию через глобальный поиск по слову «РазностьДат». Типичный вызов выглядит так:
// Примерный синтаксис — уточните в своей версии БСП
ДнейПросрочки = ОбщегоНазначения.РазностьДат(ДатаОплаты, ТекущаяДатаСеанса(), "День");Преимущество функций БСП в том, что они уже обрабатывают краевые случаи: пустые даты, перестановку аргументов, отрицательный результат. Если конфигурация не содержит БСП, функцию легко написать самостоятельно на основе вычитания и деления.
РАЗНОСТЬДАТ в запросах 1С
Когда расчёт нужен в отчёте или при выборке большого объёма данных, правильнее считать разность на стороне запроса, а не в цикле по результату. Для этого в языке запросов есть встроенная функция РАЗНОСТЬДАТ.
Синтаксис: РАЗНОСТЬДАТ(Дата1, Дата2, ЕдиницаИзмерения). Функция возвращает число полных единиц между датами. Порядок аргументов важен: если вторая дата раньше первой, результат будет отрицательным.
В качестве единицы измерения допускаются: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Учтите, что функция считает количество границ единицы между датами, а не полные интервалы в бытовом смысле: разность между 31 января и 1 февраля в месяцах даст 1, хотя прошли всего сутки. Для расчёта стажа или возраста это поведение обязательно нужно учитывать.
Расчёт разности в днях, месяцах и годах: нюансы
Разные единицы измерения ведут себя по-разному, и бездумное применение одного подхода ко всем задачам приводит к ошибкам в учётных данных.
Дни и календарные сутки
Для большинства хозяйственных расчётов (просрочка, срок доставки) подходит деление секунд на 86400 или РАЗНОСТЬДАТ с единицей ДЕНЬ. Различие появляется на границах: между 10:00 понедельника и 09:00 вторника — 23 часа, то есть 0 полных суток, но РАЗНОСТЬДАТ в днях может дать 1. Проверяйте поведение на тестовых данных с временем.
Месяцы и годы
Делить дни на 30 или 365 — грубая ошибка: месяцы имеют разную длину, а годы бывают високосными. Для расчёта полных месяцев и лет корректнее использовать функции работы с датами: ДобавитьМесяц(), Год(), Месяц(), День() и сравнение составляющих. Типовой алгоритм возраста: разность лет минус 1, если месяц и день рождения ещё не наступили в текущем году.
Процедура РассчитатьВозраст(ДатаРождения, НаДату)
Лет = Год(НаДату) - Год(ДатаРождения);
Если Месяц(НаДату) < Месяц(ДатаРождения)
Или (Месяц(НаДату) = Месяц(ДатаРождения) И День(НаДату) < День(ДатаРождения)) Тогда
Лет = Лет - 1;
КонецЕсли;
КонецПроцедурыПроизводственный календарь и рабочие дни
Частая бизнес-задача — посчитать не календарные, а рабочие дни между датами: сроки выполнения заказа, нормы выработки, кадровые расчёты. Простым вычитанием это не решается, потому что выходные и праздники нужно исключать.
В типовых конфигурациях для этого служит регистр сведений «Данные производственного календаря» и функции подсистемы «Календарные графики» БСП, например КалендарныеГрафики.РазностьДатПоКалендарю(). Функция принимает график работы, дату начала и дату окончания и возвращает количество рабочих дней по указанному графику.
Если пишете собственное решение, логика такая: запросом выбрать из регистра календаря записи между датами, где вид дня — рабочий, и посчитать их количество. Перед этим убедитесь, что производственный календарь в базе заполнен на нужный период, иначе расчёт вернёт ноль или заниженное значение.
Проверка результата и типичные ошибки
После внедрения расчёта обязательно проверьте его на граничных случаях: одинаковые даты, даты с разным временем, переход через месяц и год, пустая дата, даты в обратном порядке. Такие проверки занимают несколько минут, но отсекают большинство дефектов.
Как проверить результат
Результат равен 0
Результат 1 или отрицательное число
Ожидаемое число полных дней по вашей логике
Скачок на единицу из-за границы суток
Расчёт пропущен или выдано понятное сообщение
Огромное число секунд или дней в отчёте
Отрицательный результат или обработанная ошибка
Молчаливый неверный положительный результат
Как выбрать подходящий способ
Выбор инструмента зависит от контекста: где выполняется расчёт, какой объём данных обрабатывается и что требуется на выходе. Ориентируйтесь на следующие правила.
Как выбрать действие
Единого «правильного» способа нет: для отчёта по просрочке оптимален запрос, для разовой проверки в коде — вычитание, для кадровых расчётов — календарные функции. Главное — зафиксировать выбранную логику в одном общем модуле, чтобы все части системы считали одинаково.
Что важно запомнить
Вычитание дат в 1С даёт секунды, для дней делите на 86400. В запросах используйте РАЗНОСТЬДАТ с явной единицей измерения. Всегда проверяйте даты на заполненность, учитывайте время в составе даты, а для рабочих дней применяйте производственный календарь.
Частые вопросы
Почему при вычитании дат получается огромное число?
Результат вычитания выражен в секундах. Например, три дня — это 259200 секунд. Разделите значение на 86400, чтобы получить дни, и отбросьте дробную часть функцией Цел(), если нужны полные сутки.
Как получить разность дат без учёта времени?
Приведите обе даты к началу дня функцией НачалоДня() перед вычитанием: НачалоДня(Дата2) - НачалоДня(Дата1). Тогда время не повлияет на результат, и разность будет кратна полным суткам.
Что вернёт РАЗНОСТЬДАТ, если даты стоят в обратном порядке?
Функция вернёт отрицательное число. Это удобно для определения просрочки: положительное значение показывает, что срок прошёл, отрицательное — что он ещё не наступил. При необходимости обрабатывайте знак в условии запроса.
Как посчитать стаж или возраст в полных годах?
Вычтите год рождения из текущего года и уменьшите результат на единицу, если месяц и день рождения ещё не наступили в текущем году. Деление дней на 365 для этой задачи не подходит из-за високосных лет.
Можно ли использовать РАЗНОСТЬДАТ в условии ГДЕ запроса?
Да, функцию можно применять и в секции ГДЕ, и в условиях соединений. Это позволяет отбирать, например, только просроченные документы, не выгружая в код всю выборку. Учитывайте, что такие условия могут замедлять запрос на больших таблицах.
Что делать, если разность нужна в часах или минутах?
В коде разделите результат вычитания на 3600 для часов или на 60 для минут. В запросе передайте в РАЗНОСТЬДАТ единицу ЧАС или МИНУТА — функция вернёт число полных единиц между датами.