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

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

1С: что будет, если из одной даты вычесть другую дату

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

Во встроенном языке 1С:Предприятие операция вычитания дат — одна из самых частых при работе с документами, сроками оплаты, стажем и периодами хранения. Когда вы пишете выражение вида Дата2 - Дата1, платформа не возвращает новую дату и не возвращает структуру «годы-месяцы-дни». Результатом является число — количество секунд между двумя моментами времени.

Это поведение часто становится источником ошибок: разработчик ожидает получить «30 дней», а получает число 2592000, которое затем попадает в отчёт или печатную форму в нечитаемом виде. Чтобы корректно работать с разницей дат, нужно понимать тип результата, уметь переводить секунды в нужные единицы и знать встроенные функции для расчёта месяцев и лет.

Ниже разобрано, что именно возвращает вычитание дат, как посчитать разницу в днях, месяцах и годах, какие функции запроса помогают решить ту же задачу на уровне СУБД и какие ошибки встречаются чаще всего.

Что возвращает операция «дата минус дата»

Во встроенном языке 1С вычитание двух значений типа «Дата» даёт значение типа «Число». Это количество секунд между двумя моментами времени. Например:

Дата1 = '20260101000000';

Дата2 = '20260111000000';

Разница = Дата2 - Дата1; // 864000 (секунд, то есть 10 дней)

Порядок операндов важен. Если вычесть из более ранней даты более позднюю, результат будет отрицательным числом. Платформа не выдаёт ошибку и не «обрезает» значение — знак результата полностью на вашей ответственности, поэтому перед расчётом сроков стоит проверять, какая дата больше.

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

Как получить разницу в днях, часах и минутах

Поскольку результат вычитания — секунды, перевод в нужные единицы выполняется делением:

  • минуты — разделить на 60;
  • часы — разделить на 3600;
  • дни — разделить на 86400 (60 × 60 × 24).
РазницаВСекундах = ДатаОкончания - ДатаНачала;

РазницаВДнях = РазницаВСекундах / 86400;

Обратите внимание на дробную часть. Если даты содержат время (например, документ проведён в 14:30, а срок наступает в 09:00), результат деления будет дробным: 2,77 дня. Для бизнес-логики «срок в календарных днях» обычно нужно отбросить время перед вычитанием с помощью функции НачалоДня():

ДнейПросрочки = (НачалоДня(ТекущаяДата()) - НачалоДня(СрокОплаты)) / 86400;

Такой приём гарантирует целое число дней и избавляет от ситуации, когда «сегодня вечером» и «завтра утром» считаются одним днём или, наоборот, двумя в зависимости от времени суток.

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

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

Простым делением на секунды месяцы и годы не вычисляются корректно: в месяце может быть от 28 до 31 дня, а в году 365 или 366 дней. Поэтому для таких расчётов используют два подхода.

Первый — функция языка запросов РАЗНОСТЬДАТ. Она вычисляется на стороне СУБД и возвращает целое число полных единиц указанного типа:

ВЫБРАТЬ

РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, МЕСЯЦ) КАК Месяцев,

РАЗНОСТЬДАТ(&ДатаНачала, &ДатаОкончания, ДЕНЬ) КАК Дней

Третий параметр может принимать значения СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Важно понимать: функция считает количество границ указанного периода между датами, поэтому «с 31 января по 1 февраля» даст один месяц, хотя прошли сутки.

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

Для сдвига даты на целые месяцы используйте функцию ДобавитьМесяц(Дата, КоличествоМесяцев) — она корректно обрабатывает переход через год и разную длину месяцев.

Вычитание дат в запросах: типичные сценарии

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

Пример отбора документов, оплата по которым просрочена более чем на 5 дней:

ВЫБРАТЬ

Реализация.Ссылка КАК Документ,

РАЗНОСТЬДАТ(Реализация.ДатаОплаты, &ТекущаяДата, ДЕНЬ) КАК ДнейПросрочки

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

ГДЕ

РАЗНОСТЬДАТ(Реализация.ДатаОплаты, &ТекущаяДата, ДЕНЬ) > 5

Для добавления интервала к дате в запросе используется функция ДОБАВИТЬКДАТЕ(Дата, ТипПериода, Количество). Она удобна, когда нужно вычислить «срок оплаты = дата отгрузки + 14 дней» прямо в выборке, без обхода результата в коде.

Учтите, что вычисления в условии ГДЕ по некоторым СУБД могут замедлять выполнение запроса на больших таблицах, так как индекс по дате не используется. Если документов много, эффективнее заранее вычислить граничную дату в коде и сравнивать поле с параметром.

Способы посчитать разницу дат

Вычитание в коде (Дата2 - Дата1)

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

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

Считает дни, месяцы, годы на стороне СУБД; подходит для отборов, но считает по границам периодов

Собственная функция в общем модуле

Точный расчёт «лет/месяцев/дней» для стажа и возраста; требует однократной разработки и тестирования

Типичные ошибки при работе с разницей дат

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

Вторая частая проблема — игнорирование составляющей времени. Даты документов почти всегда содержат время, поэтому разница «в днях» получается дробной, а сравнение вида Разница = 3 не срабатывает. Решение — приведение к началу дня перед вычитанием.

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

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

Типичные ошибки
01
Считать результат вычитания днями — на самом деле это секунды, отчёт показывает огромные числа
02
Не отбрасывать время — разница в днях получается дробной, сравнения не срабатывают
03
Не проверять пустые даты — разница с '00010101' искажает показатели
04
Перепутать порядок операндов — отрицательный результат ломает условия просрочки
05
Прибавлять секунды для сдвига на месяц — месяцы разной длины, дата «уезжает»

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

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

Для отладки во встроенном языке используйте Сообщить() или точку останова в конфигураторе и смотрите фактическое значение и его тип. Если переменная содержит число вместо ожидаемой даты — вы видите результат вычитания, а не дату.

При сомнениях в логике «полных месяцев» проверяйте граничные случаи: с 31 января по 28 февраля, с 29 февраля високосного года, переход через новый год. Именно на таких датах расходятся результаты РАЗНОСТЬДАТ и самописных алгоритмов.

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

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

Разница ровно в сутки
Норма

86400 секунд или 1 день после деления

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

Дробное число или значение в другом масштабе

Сравнение дат без учёта времени
Норма

Обе даты приведены через НачалоДня()

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

Результат зависит от часов и минут документа

Пустой реквизит даты
Норма

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

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

Огромная разница из-за даты '00010101'

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

Какой тип данных возвращает выражение «дата минус дата» в 1С?

Возвращается значение типа «Число» — количество секунд между двумя моментами времени. Это не дата и не строка вида «5 дней». Чтобы получить дни, разделите результат на 86400.

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

Для дней можно вычесть соответствующее число секунд: Дата - 7 * 86400. Для месяцев используйте ДобавитьМесяц(Дата, -3) — функция корректно обработает переход через год и разную длину месяцев.

Почему разница в днях получается дробной?

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

Чем РАЗНОСТЬДАТ отличается от вычитания в коде?

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

Что будет, если одна из дат не заполнена?

Незаполненная дата равна '00010101000000'. Разница с ней превратится в огромное число секунд без ошибки выполнения, что незаметно испортит отчёт. Всегда проверяйте даты через ЗначениеЗаполнено() перед расчётом.

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

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

Итог

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

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