Разработка и Конфигурация · 9 мин
Как вычитать даты в 1С: способы, функции и примеры
Как вычитать даты в 1С: оператор минус, функция РазностьДат, вычисление дней, месяцев и лет между датами. Примеры кода, запросы и типичные ошибки.
Вычитание дат — одна из самых частых задач при разработке и доработке конфигураций 1С: расчёт стажа сотрудника, срока хранения товара, просрочки оплаты, возраста контрагента. Встроенный язык 1С предлагает несколько подходов, и выбор между ними зависит от того, какой результат нужен — количество секунд, дней, месяцев или лет.
Главная тонкость в том, что простой оператор «минус» для двух дат возвращает разность в секундах, а не в днях. Это регулярно становится причиной ошибок в расчётах, когда разработчик забывает пересчитать результат. Для корректного вычисления разности в календарных единицах существует специальная функция РазностьДат, а в запросах — своя конструкция РАЗНОСТЬДАТ.
Ниже разобраны все рабочие способы: от простейшего вычитания в коде до вычислений в запросах и на форме, с примерами, ограничениями и типичными ошибками.
Вычитание дат оператором «минус»: что получится на выходе
Самый интуитивный способ — просто вычесть одну дату из другой. Встроенный язык это позволяет, но результат будет числом — количеством секунд между двумя моментами времени.
ДатаНачала = '20260101120000';
ДатаОкончания = '20260110120000';
Разность = ДатаОкончания - ДатаНачала;
// Результат: 777600 (секунд)
Чтобы получить дни, результат нужно разделить на количество секунд в сутках — 86400. Это рабочий приём, когда даты содержат только день без времени или когда точность до долей дня не критична:
КоличествоДней = (ДатаОкончания - ДатаНачала) / 86400;
Ограничение метода очевидно: секунды неудобно пересчитывать в месяцы и годы, потому что длительность месяца не постоянна. Для таких задач нужен другой инструмент.
Функция РазностьДат: разность в днях, месяцах и годах
Штатный способ вычислить разность в календарных единицах — функция РазностьДат. Она принимает три параметра: начальную дату, конечную дату и тип разности.
РазностьВДнях = РазностьДат(ДатаНачала, ДатаОкончания, ТипРазностиДат.День);
РазностьВМесяцах = РазностьДат(ДатаНачала, ДатаОкончания, ТипРазностиДат.Месяц);
РазностьВГодах = РазностьДат(ДатаНачала, ДатаОкончания, ТипРазностиДат.Год);
Перечисление ТипРазностиДат поддерживает значения: Секунда, Минута, Час, День, Месяц, Квартал, Год. Функция считает количество полных единиц указанного типа, укладывающихся между датами.
Обратите внимание на порядок параметров: сначала меньшая (более ранняя) дата, затем большая. Если перепутать их местами, результат будет отрицательным. Это не ошибка, но в расчётах стажа или просрочки отрицательное значение обычно требует отдельной обработки.
РазностьВДнях = РазностьДат(ДатаНачала, ДатаОкончания, ТипРазностиДат.День);Разность дат в запросе: функция РАЗНОСТЬДАТ
В языке запросов 1С действует своя функция — РАЗНОСТЬДАТ. Она удобна, когда нужно посчитать разность сразу для множества строк, например просрочку по всем неоплаченным счетам, не выгружая данные в код.
ВЫБРАТЬ
Счет.Ссылка КАК Счет,
РАЗНОСТЬДАТ(Счет.ДатаОплаты, &ТекущаяДата, ДЕНЬ) КАК ДнейПросрочки
ИЗ
Документ.СчетНаОплату КАК Счет
ГДЕ
Счет.Оплачен = ЛОЖЬ
В качестве единицы измерения указываются ключевые слова: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Синтаксис отличается от встроенного языка — здесь не используется перечисление, а единица пишется просто словом.
Практическое преимущество запросного варианта — производительность. Вычисление выполняется на стороне СУБД, и вы получаете готовую колонку без обхода выборки в цикле. Для отчётов по большим объёмам данных это заметно быстрее.
Как прибавить или вычесть из даты заданный период
Обратная задача встречается не реже: нужно не найти разность, а получить новую дату, сдвинутую на заданное число дней или месяцев. Для секунд, минут, часов и дней достаточно арифметики, для месяцев и лет — функции ДобавитьМесяц.
// Прибавить 10 дней
НоваяДата = ИсходнаяДата + 10 * 86400;
// Вычесть 3 месяца
НоваяДата = ДобавитьМесяц(ИсходнаяДата, -3);
// Прибавить год
НоваяДата = ДобавитьМесяц(ИсходнаяДата, 12);
Функция ДобавитьМесяц корректно обрабатывает переходы через границы года и разную длину месяцев: при прибавлении месяца к 31 января результатом будет последний день февраля, а не несуществующая дата. Именно поэтому складывать месяцы через секунды нельзя.
Сравнение вариантов
Подходит для секунд и дней при датах без времени. Не работает для месяцев и лет, требует ручного пересчёта.
Универсальный способ в коде для любых единиц от секунды до года. Считает только полные единицы, порядок дат влияет на знак.
Оптимально для выборок и отчётов: расчёт на стороне СУБД без циклов. Синтаксис отличается от встроенного языка.
Для сдвига даты на месяцы и годы. Корректно обрабатывает концы месяцев, но не вычисляет разность.
Расчёт возраста и стажа: полные годы между датами
Типовая прикладная задача — посчитать возраст сотрудника или стаж работы в полных годах. Функция РазностьДат с типом «Год» считает именно полные годы, поэтому базовый расчёт прост:
Возраст = РазностьДат(ДатаРождения, ТекущаяДатаСеанса(), ТипРазностиДат.Год);
Однако результат стоит проверить на граничных случаях. Если день рождения в текущем году ещё не наступил, функция уже может вернуть полный год в зависимости от алгоритма округления внутри платформы. Надёжнее дополнительно сверить месяц и день и при необходимости скорректировать результат на единицу.
Для стажа в формате «лет, месяцев, дней» расчёт выполняют последовательно: сначала полные годы, затем остаток в месяцах от даты, сдвинутой на эти годы, затем остаток в днях. Такой поэтапный подход исключает накопление погрешности.
- 1Определите, в каких единицах нужен результат: секунды, дни, месяцы или годы
- 2Для секунд и дней используйте оператор «минус» с пересчётом через 86400
- 3Для месяцев, кварталов и лет примените РазностьДат с нужным типом
- 4Для массовых расчётов в отчётах используйте РАЗНОСТЬДАТ в запросе
- 5Проверьте результат на граничных датах: конец месяца, високосный год, даты со временем
Типичные ошибки и как их избежать
Большинство проблем с вычитанием дат связано не с функциями, а с неверными допущениями о данных. Дата в 1С всегда хранит время, даже если на форме отображается только день, и это источник неочевидных расхождений.
Вторая группа ошибок — перепутанный порядок аргументов и ожидание дробного результата там, где функция возвращает только целые полные единицы.
Проверка результата и контрольные точки
Любой расчёт разности дат стоит проверить на контрольных примерах до включения в рабочий код. Достаточно трёх-пяти пар дат с заранее известным результатом, чтобы выявить ошибку единицы измерения или порядка аргументов.
Как проверить результат
10 дней или 864000 секунд
Любое другое значение — перепутана единица измерения
0 полных месяцев
1 месяц — проверьте логику граничных дат
Результат отрицательный, модуль совпадает с прямым расчётом
Ошибка выполнения или ноль — проверьте заполненность дат
0 полных дней
1 день — время не учтено в логике
Для дат, которые могут быть не заполнены, добавьте проверку на пустое значение: пустая дата в 1С равна '00010101', и разность с ней даст огромное число, которое испортит отчёт. Проверка через ЗначениеЗаполнено(Дата) перед расчётом — обязательный элемент надёжного кода.
Что важно запомнить
Оператор «минус» даёт секунды, РазностьДат — полные календарные единицы, РАЗНОСТЬДАТ — то же самое в запросах, ДобавитьМесяц — сдвиг даты на месяцы и годы. Всегда проверяйте время внутри дат, порядок аргументов и заполненность значений.
Частые вопросы
Почему вычитание дат даёт огромное число вместо дней?
Потому что оператор «минус» возвращает разность в секундах. Чтобы получить дни, разделите результат на 86400, а для месяцев и лет используйте функцию РазностьДат с соответствующим типом разности.
Как посчитать разность дат без учёта времени?
Приведите обе даты к началу дня функцией НачалоДня(Дата) перед вычитанием. Тогда время не повлияет на результат, и разность в днях будет соответствовать календарному числу суток.
Что вернёт РазностьДат, если даты одинаковые?
Ноль для любого типа разности. Между двумя одинаковыми моментами времени нет полных единиц ни одного типа, поэтому результат всегда равен нулю.
Как вычесть из даты рабочие дни, а не календарные?
Штатных функций для этого нет. Используйте производственный календарь: в типовых конфигурациях есть регистры и методы для расчёта по графику работы, в самописных решениях придётся перебирать дни в цикле с проверкой по календарю.
Можно ли вычитать даты прямо в формуле поля компоновки данных?
Да, в СКД доступны выражения с функцией РАЗНОСТЬДАТ на языке выражений компоновки. Это позволяет вычислять разность в ресурсах и вычисляемых полях отчёта без изменения запроса.
Что делать, если одна из дат может быть пустой?
Проверяйте её через ЗначениеЗаполнено перед расчётом. Пустая дата равна 01.01.0001, и разность с ней даст некорректное огромное значение, которое исказит отчёт или расчёт.