Расчет разницы между датами — одна из самых частых задач при разработке в 1С:Предприятие 8.3. Без этого не обойтись при расчете просроченных задолженностей, определении стажа сотрудников, анализе временных интервалов в отчетах или автоматизации бизнес-процессов. Казалось бы, простая операция, но в есть несколько способов получить разность дат — от элементарных встроенных функций до сложных запросов с группировкой по периодам.

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

1. Встроенная функция РазностьДат: синтаксис и подводные камни

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

РазностьДат(Дата2, Дата1, ЕдиницаИзмерения)

Где ЕдиницаИзмерения может принимать значения:

  • 🕒 "С" — секунды
  • 🕒 "М" — минуты
  • 🕒 "Ч" — часы
  • 📅 "Д" — дни (самый популярный вариант)
  • 📆 "МЕС" — месяцы
  • 🗓️ "КВ" — кварталы
  • 📅 "ГОД" — годы

Пример кода:

ДатаНачала ='2026-01-15';

ДатаОкончания ='2026-02-20';

РазницаВДнях = РазностьДат(ДатаОкончания, ДатаНачала,"Д");

// Вернет 36 (дней)

💡

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

⚠️ Внимание: Функция учитывает астрономическое время, а не календарные сутки. Это означает, что разница между '2026-01-01 23:59:59' и '2026-01-02 00:00:01' составит 2 секунды, а не 1 день. Для бизнес-логики это часто критично!

2. Альтернативный метод: вычитание дат как чисел

Менее известный, но эффективный способ — воспользоваться тем, что в даты внутренне хранятся как числа (количество секунд с 1 января 1899 года). Их можно просто вычесть:

Дата1 ='2026-01-01';

Дата2 ='2026-01-10';

РазницаВСекундах = Дата2 - Дата1;

// Вернет 777600 (секунд = 9 дней)

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

РазницаВДнях = (Дата2 - Дата1) / 86400;

Преимущества метода:

  • ⚡ Быстрее работает на больших массивах данных
  • 🔧 Позволяет гибко настраивать единицы измерения (например, получить часы с дробной частью)
  • 📊 Легко интегрируется в математические выражения

⚠️ Внимание: При вычитании дат с временем результат будет включать дробную часть (часы/минуты). Для чисто календарных расчетов предварительно применяйте НачалоДня.

📊 Какой метод расчета разницы дат вы используете чаще?
Встроенная функция РазностьДат
Вычитание дат как чисел
Запросы 1С
Собственные функции на встроенном языке
Другой вариант

3. Расчет разности в запросах 1С (SQL-подобный синтаксис)

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

Пример запроса:

ВЫБРАТЬ

ЗаказыПокупателей.Номер КАК НомерЗаказа,

РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА, ЗаказыПокупателей.Дата,"Д") КАК ПросрочкаДней

ИЗ

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

ГДЕ

ЗаказыПокупателей.Статус = ЗНАЧЕНИЕ(Справочник.СтатусыЗаказов.НеВыполнен)

Особенности работы с РАЗНОСТЬДАТ в запросах:

  • 📊 Можно использовать в ВЫБРАТЬ, ГДЕ и УПОРЯДОЧИТЬ ПО
  • 🔄 Поддерживает те же единицы измерения, что и встроенная функция
  • ⚡ Работает значительно быстрее, чем построчный расчет в цикле

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

ВЫБРАТЬ

НЕДЕЛЯ(Документы.Дата) КАК Неделя,

СУММА(РАЗНОСТЬДАТ(Документы.ДатаОплаты, Документы.Дата,"Д")) / КОЛИЧЕСТВО(*) КАК СредняяПросрочка

ИЗ

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

СГРУППИРОВАТЬ ПО

НЕДЕЛЯ(Документы.Дата)

4. Учет рабочих и календарных дней

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

Вариант 1. Использовать справочник"ПроизводственныеКалендари"

В типовой конфигурации 1С:ERP или 1С:Управление торговлей есть справочник с предопределенными календарями. Пример кода:

Календарь = Справочники.ПроизводственныеКалендари.ОсновнойКалендарь;

Разница = Календарь.РазностьДат(ДатаОкончания, ДатаНачала);

// Вернет количество рабочих дней

Вариант 2. Самописная функция с учетом выходных

Если типового календаря нет, можно написать собственную функцию:

Функция РабочиеДниМеждуДатами(ДатаНачала, ДатаОкончания)

ДатаТекущая = НачалоДня(ДатаНачала);

КоличествоДней = 0;

Пока ДатаТекущая <= ДатаОкончания Цикл

Если НЕ (ДеньНедели(ДатаТекущая) = 6 ИЛИ ДеньНедели(ДатаТекущая) = 7) Тогда

КоличествоДней = КоличествоДней + 1;

КонецЕсли;

ДатаТекущая = ДатаТекущая + 86400; // +1 день

КонецЦикла;

Возврат КоличествоДней;

КонецФункции

⚠️ Внимание: Не забывайте про праздничные дни, которые могут выпадать на будни! Для точных расчетов нужно интегрировать официальный производственный календарь РФ (обновляется ежегодно).

☑️ Подготовка к расчету рабочих дней

Выполнено: 0 / 4

5. Работа с часовыми поясами и летним временем

Если ваша система работает в нескольких часовых поясах (например, филиалы компании в разных регионах), стандартные функции могут давать некорректные результаты. Проблема усугубляется при переходе на зимнее/летнее время, когда местное время сдвигается на час.

Решение 1. Хранить даты в UTC

Лучшая практика — сохранять все даты в базе в формате UTC (всемирное координированное время), а при отображении конвертировать в локальное время пользователя:

// Преобразование в UTC

ДатаUTC = ДатаЛокальная + ЧасовойПояс * 3600;

// Обратное преобразование

ДатаЛокальная = ДатаUTC - ЧасовойПояс * 3600;

Решение 2. Использовать функцию"ЛокальнаяДата"

В современных версиях платформы есть функция ЛокальнаяДата, которая автоматически учитывает настройки часовых поясов текущего пользователя:

ДатаСервера = ТекущаяДата;

ДатаПользователя = ЛокальнаяДата(ДатаСервера);

Сценарий Проблема Решение
Филиалы в разных часовых поясах Разница между датами считается некорректно Хранить даты в UTC, конвертировать при отображении
Переход на зимнее/летнее время Разница в часах может"потеряться" или удвоиться Использовать ЛокальнаяДата или библиотеку работы с поясами
Расчет времени выполнения задач Время может отличаться у исполнителей в разных регионах Привязывать задачи к UTC и конвертировать в локальное время при отчетах

⚠️ Внимание: Настройки часовых поясов в берутся из операционной системы сервера и клиентских машин. Если они не синхронизированы, возможны расхождения! Проверяйте настройки через Администрирование → Настройки программы → Часовые пояса.

6. Оптимизация производительности для больших данных

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

1. Кэширование результатов

Если один и тот же интервал дат используется многократно (например, в отчете за месяц), закэшируйте результат:

Процедура ПолучитьКэшированнуюРазницу(Дата1, Дата2)

КлючКэша ="Разница_" + Формат(Дата1,"ДЛФ=DT") +"_" + Формат(Дата2,"ДЛФ=DT");

Если НЕ Кэш.Получить(КлючКэша, Разница) Тогда

Разница = РазностьДат(Дата2, Дата1,"Д");

Кэш.Поместить(КлючКэша, Разница, 3600); // Кэш на 1 час

КонецЕсли;

Возврат Разница;

КонецПроцедуры

2. Массовая обработка в запросах

Как показано в разделе 3, использование РАЗНОСТЬДАТ в запросе в десятки раз быстрее, чем построчный расчет в цикле.

3. Предварительный расчет

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

РегистрСведений.РазницыДат

- Измерение: ДокументСсылка (Тип: Документ.ЗаказПокупателя)

- Ресурс: ПросрочкаДней (Тип: Число, 10, 0)

Для максимальной производительности комбинируйте эти методы. Например:

  1. Рассчитайте разницы в фоне и сохраните в регистре
  2. В отчете берите готовые значения из регистра
  3. Обновляйте кэш раз в час
💡

Для массивов данных свыше 10 000 записей запросы 1С работают в 50-100 раз быстрее, чем построчная обработка на встроенном языке.

7. Типичные ошибки и как их избежать

Даже опытные разработчики иногда допускают ошибки при работе с датами. Вот самые распространенные:

Ошибка 1. Игнорирование времени

Если не обнулить время у дат функцией НачалоДня, разница между '2026-01-01 23:59:59' и '2026-01-02 00:00:01' составит 2 секунды вместо 1 дня. Всегда приводите даты к началу дня для календарных расчетов!

Ошибка 2. Неучет високосных годов

Функция РазностьДат корректно обрабатывает високосные годы, но если вы пишете собственную логику (например, прибавляете 365 дней к дате), не забывайте про 29 февраля:

// Некорректно для 29.02.2026

НоваяДата = ДатаНачала + 365 * 86400; // Пропустит 29.02.2026

// Корректно

НоваяДата = ДобавитьМесяц(ДобавитьГод(ДатаНачала, 1), 0);

Ошибка 3. Путаница с часовыми поясами

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

Ошибка 4. Неоптимальные расчеты в циклах

Избегайте таких конструкций:

// Плохо (медленно для больших массивов)

Для Каждого Строка Из Таблица Цикл

Строка.Разница = РазностьДат(Строка.Дата2, Строка.Дата1,"Д");

КонецЦикла;

Лучше используйте запросы или массовые операции.

Что будет если не учитывать часовые пояса?

При сравнении дат между филиалами в Москве (+3 UTC) и Владивостоке (+10 UTC) разница в 7 часов может привести к ошибкам в отчетах. Например, документ, созданный в 18:00 по московскому времени, во Владивостоке будет иметь дату следующего дня (01:00), что исказит аналитику по дням.

FAQ: Частые вопросы по разности дат в 1С

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

Используйте комбинацию функций Год и Месяц:

РазницаМесяцев = (Год(Дата2) - Год(Дата1)) * 12 + (Месяц(Дата2) - Месяц(Дата1));

Если День(Дата2) < День(Дата1) Тогда

РазницаМесяцев = РазницаМесяцев - 1;

КонецЕсли;

Этот метод учитывает, что 1.03 и 15.04 — это 1 полный месяц и 14 дней, а не 2 месяца.

Почему РазностьДат возвращает отрицательное значение?

Функция вычитает первую дату из второй (Дата2 - Дата1). Если Дата1 позже Дата2, результат будет отрицательным. Чтобы избежать этого, используйте:

Разница = Абс(РазностьДат(Дата2, Дата1,"Д"));
Как посчитать количество полных недель между датами?

Разделите разницу в днях на 7 и округлите вниз:

ПолныхНедель = Цел(РазностьДат(Дата2, Дата1,"Д") / 7);

Для учета неполных недель используйте Окр вместо Цел.

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

Да, но стандартной функции нет. Используйте такой код:

Функция РазницаВГодах(Дата1, Дата2)

Возврат Год(Дата2) - Год(Дата1) -

?(Месяц(Дата2) < Месяц(Дата1) ИЛИ

(Месяц(Дата2) = Месяц(Дата1) И День(Дата2) < День(Дата1)), 1, 0);

КонецФункции

Как учитывать праздничные дни в расчетах?

Создайте справочник"ПраздничныеДни" с датами и модифицируйте функцию расчета рабочих дней:

Функция РабочиеДниСПраздниками(ДатаНачала, ДатаОкончания)

//... базовая логика из раздела 4...

Если Справочники.ПраздничныеДни.НайтиПоНаименованию(Формат(ДатаТекущая,"ДЛФ=Д")) <> Неопределено Тогда

Продолжить; // Пропускаем праздничный день

КонецЕсли;

//...

КонецФункции

Не забудьте обновлять справочник раз в год!