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

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

Как узнать разницу дат в 1С

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

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

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

Ниже разобраны все рабочие способы получить разницу дат: в коде на встроенном языке, в запросах, в СКД и в типовых механизмах вроде расчёта стажа в ЗУП. Для каждого способа указаны единицы измерения результата, ограничения и типичные ошибки.

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

Тип «Дата» в 1С включает и календарную дату, и время с точностью до секунды. Даже если в документе отображается только «15.03.2026», внутри хранится значение «15.03.2026 0:00:00». Поэтому два документа за один день, созданные в разное время, формально имеют разные даты.

Из этого следуют два практических правила. Первое: вычитание дат оператором «минус» даёт число секунд между моментами, а не дней. Чтобы получить дни, результат нужно разделить на 86400 (количество секунд в сутках). Второе: перед сравнением или вычитанием дат с разным временем их часто приводят к началу дня функцией НачалоДня(), иначе разница в несколько часов может исказить расчёт.

Функция РазностьДат() в коде

Основной инструмент встроенного языка — функция РазностьДат(НачальнаяДата, КонечнаяДата, ТипРазности). Третий параметр задаёт единицу измерения и принимает значения перечисления ТипРазностиДат: Секунда, Минута, Час, День, Месяц. Если тип не указан, по умолчанию используется секунда.

НачалоПериода = Дата(2026, 1, 10);

КонецПериода = Дата(2026, 3, 25);

ДнейМежду = РазностьДат(НачалоПериода, КонецПериода, ТипРазностиДат.День);

МесяцевМежду = РазностьДат(НачалоПериода, КонецПериода, ТипРазностиДат.Месяц);

СекундМежду = РазностьДат(НачалоПериода, КонецПериода); // по умолчанию секунды

Обратите внимание на поведение при расчёте в месяцах: функция считает только полные месяцы. Между 10 января и 9 марта разница составит один полный месяц, а не два, хотя календарно затронуты три месяца. Если нужно считать «календарные» месяцы с округлением, логику придётся дописывать вручную.

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

bsl
ДнейПросрочки = РазностьДат(ДатаОплатыПоДоговору, ТекущаяДатаСеанса(), ТипРазностиДат.День);

Вычитание дат напрямую и перевод секунд в дни

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

РазницаВСекундах = ДатаОкончания - ДатаНачала;

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

РазницаВЧасах = Цел(РазницаВСекундах / 3600);

Ограничение способа очевидно: он не умеет считать месяцы и годы, потому что длительность месяца непостоянна. Для месяцев используйте только РазностьДат() или запрос. Также помните, что операция Цел() отбрасывает дробную часть — если нужно округление до ближайшего целого, применяйте Окр().

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

В языке запросов 1С есть собственный оператор РАЗНОСТЬДАТ(<Дата1>, <Дата2>, <Тип>). Он возвращает целое число — количество единиц указанного типа между датами. Допустимые типы: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, ГОД. В отличие от функции встроенного языка, здесь доступен расчёт в годах.

ВЫБРАТЬ

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

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

ИЗ

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

Ключевое ограничение оператора: он вычисляет разницу именно в указанных единицах, отбрасывая остаток. Разница в 1 год и 11 месяцев при типе ГОД даст 1, а при типе МЕСЯЦ — 23. Чтобы получить представление вида «2 года 3 месяца 5 дней», нужно последовательно вычислять годы, затем месяцы остатка, затем дни — либо делать это уже в коде после запроса.

В запросах также доступна функция ДОБАВИТЬКДАТЕ(Дата, Тип, Количество) — обратная операция, полезная для проверки результата: если прибавить к первой дате вычисленную разницу, должна получиться вторая дата (с точностью до отброшенного остатка).

Сравнение способов

РазностьДат() в коде

Подходит для вычислений в модуле, обработках, расчёте реквизитов. Нет типа «Год», месяцы считаются только полные.

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

Подходит для отборов, отчётов и СКД: разница считается на сервере СУБД без выгрузки данных. Есть тип ГОД.

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

Самый простой вариант для секунд, часов и дней. Не подходит для месяцев и лет из-за разной длины месяца.

Разница дат в СКД и отчётах

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

Альтернатива — вычисляемое поле СКД с выражением на языке выражений компоновки. Такой подход оправдан, когда разница зависит от параметров отчёта (например, от выбранной пользователем даты отсечки), но помните: вычисления на уровне СКД выполняются после получения данных и при больших объёмах работают медленнее, чем расчёт в запросе.

Типичный сценарий — отчёт по дебиторской задолженности с колонкой «Дней просрочки». Правильное решение: в запросе набора данных вычислить РАЗНОСТЬДАТ(ДатаОплаты, &ДатаОтчета, ДЕНЬ) и дополнительно сгруппировать задолженность по интервалам (до 30 дней, 30–60, свыше 60) через конструкцию ВЫБОР.

Порядок действий для отчёта по просрочке
  1. 1
    Определите дату отсечки: параметр отчёта или ТекущаяДатаСеанса()
  2. 2
    В запросе набора данных добавьте поле РАЗНОСТЬДАТ(ДатаПлановойОплаты, &ДатаОтчета, ДЕНЬ)
  3. 3
    Отфильтруйте строки, где разница больше нуля — это просроченная задолженность
  4. 4
    Проверьте результат на 2–3 документах, пересчитав дни вручную по календарю

Расчёт стажа и возраста: полные годы, месяцы, дни

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

ПолныхЛет = Год(ДатаКонец) - Год(ДатаНачало);

Если Месяц(ДатаКонец) < Месяц(ДатаНачало)

Или (Месяц(ДатаКонец) = Месяц(ДатаНачало) И День(ДатаКонец) < День(ДатаНачало)) Тогда

ПолныхЛет = ПолныхЛет - 1;

КонецЕсли;

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

Типичные ошибки и проверка результата

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

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

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

Для проверки корректности расчёта возьмите пару дат с очевидной разницей (например, ровно месяц или ровно год) и убедитесь, что алгоритм выдаёт ожидаемое значение. Затем проверьте граничные случаи: даты в пределах одного дня, переход через високосный февраль, конец и начало месяца с разным числом дней.

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

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

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

86400 секунд или 1 день

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

86399 или 0 — даты содержат разное время

Расчёт с пустой датой
Норма

Ветка не выполняется, поле пустое

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

Огромное число дней в отчёте

Полный месяц между датами
Норма

РазностьДат возвращает 1 месяц

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

0 месяцев при визуально «полном» месяце — проверьте день начала и конца

FAQ

Как получить разницу дат в днях в запросе 1С?

Используйте оператор РАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ). Он вернёт целое число полных дней между датами. Если нужны часы или минуты, замените третий параметр на ЧАС или МИНУТУ.

Почему вычитание дат даёт 86400 вместо 1 дня?

Потому что результат вычитания двух значений типа «Дата» — это число секунд между ними. 86400 секунд — это ровно одни сутки. Разделите результат на 86400, чтобы получить дни.

Как посчитать количество полных лет между датами?

В запросе — РАЗНОСТЬДАТ(Дата1, Дата2, ГОД). В коде функция РазностьДат не поддерживает годы, поэтому годы вычисляют вручную: из разности годов вычитают единицу, если месяц и день конечной даты раньше начальной.

Что делать, если одна из дат может быть пустой?

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

Можно ли получить разницу вида «2 года 3 месяца 5 дней» одной функцией?

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

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

Функция кода поддерживает типы от секунды до месяца и выполняется на клиенте или сервере приложений. Оператор запроса дополнительно умеет считать годы и выполняется на стороне СУБД, что быстрее при обработке больших выборок.

Итог

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

Вычитание дат даёт секунды, для дней делите на 86400. В коде используйте РазностьДат(), в запросах — РАЗНОСТЬДАТ с типом ДЕНЬ, МЕСЯЦ или ГОД. Всегда проверяйте пустые даты и приводите значения к началу дня, если время не важно.