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

В этой статье разберём все способы вычитания дат в 1С 8.3 и 1С 8.2, включая встроенные функции РазностьДат(), День()/Месяц()/Год(), а также практические примеры для типичных задач. Особое внимание уделим типичным ошибкам, которые приводят к некорректным результатам, и нюансам работы с временными зонами, високосными годами и рабочими календарями.

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

📊 Для каких задач вам чаще всего нужно вычитать даты в 1С?
Расчёт просрочек по платежам
Определение стажа сотрудников
Анализ интервалов между заказами
Начисление пени/штрафов
Другое

1. Базовые функции для работы с датами в 1С

Платформа 1С:Предприятие предоставляет несколько встроенных инструментов для манипуляций с датами. Основные из них:

  • 📅 РазностьДат() — ключевая функция для вычитания дат, возвращает разницу в днях, месяцах или годах.
  • 🗓️ Дата() — создаёт значение типа Дата из отдельных компонентов (год, месяц, день).
  • ДобавитьМесяц()/ДобавитьДень() — сдвигают дату на заданный интервал.
  • 🔢 День(), Месяц(), Год() — извлекают компоненты даты для ручных расчётов.

Самая универсальная функция — РазностьДат(). Её синтаксис:

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

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

  • "День" — разница в днях (по умолчанию);
  • "Месяц" — разница в полных месяцах;
  • "Год" — разница в полных годах.
⚠️ Внимание: Функция РазностьДат() учитывает рабочие дни только если используется вместе с параметром Календарь (доступно в некоторых конфигурациях). По умолчанию выходные и праздники игнорируются!

Пример простого вычитания:

Результат = РазностьДат(Дата2, Дата1, "День"); // Вернёт количество дней между Дата1 и Дата2

2. Практические примеры вычитания дат

Рассмотрим реальные сценарии, где требуется вычесть одну дату из другой.

2.1. Расчёт просрочки платежа

Допустим, у вас есть дата оплаты по счёту (ДатаОплаты) и текущая дата. Нужно узнать, сколько дней просрочки:

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

Если ДниПросрочки > 0 Тогда

Сообщить("Просрочка: " + ДниПросрочки + " дней");

КонецЕсли;

2.2. Определение стажа сотрудника

Для кадрового учёта часто требуется посчитать стаж в годах и месяцах:

ГодыСтажа  = РазностьДат(ТекущаяДата(), ДатаПриема, "Год");

МесяцыСтажа = РазностьДат(ТекущаяДата(), ДобавитьГод(ДатаПриема, ГодыСтажа), "Месяц");

Сообщить("Стаж: " + ГодыСтажа + " лет и " + МесяцыСтажа + " месяцев");

Проверьте формат дат (должен быть тип "Дата")

Убедитесь, что первая дата НЕ раньше второй (иначе результат отрицательный)

Учитывайте временные зоны, если работаете с сервером и клиентом

Для рабочих дней используйте параметр "Календарь" (если доступен)-->

2.3. Анализ интервалов между заказами

В торговле полезно знать средний интервал между покупками клиента:

ИнтервалДней = РазностьДат(ДатаПоследнегоЗаказа, ДатаПредыдущегоЗаказа, "День");

СреднийИнтервал = ИнтервалДней / КоличествоЗаказов;

⚠️ Внимание: При расчёте интервалов между датами в 1С:Управление Торговлей учитывайте, что функция РазностьДат() не rounds результат. Например, разница между "01.01.2023" и "03.01.2023" составит 2 дня, а не 3.

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

Даже опытные разработчики сталкиваются с ошибками при вычитании дат. Вот самые распространённые:

  • Перепутан порядок дат: РазностьДат(Дата1, Дата2) вернёт отрицательное значение, если Дата1 раньше Дата2. Всегда проверяйте порядок!
  • Игнорирование времени: Если даты содержат время (например, "01.01.2023 23:59:59"), разница может оказаться на 1 день меньше ожидаемой. Используйте НачалоДня() для нормализации:
КорректнаяРазница = РазностьДат(НачалоДня(Дата2), НачалоДня(Дата1), "День");
  • Високосные годы: Функция РазностьДат() корректно учитывает високосные годы, но при ручных расчётах (например, через ДеньГода()) можно получить ошибку.
  • Рабочие календари: Без учёта выходных и праздников расчёт просрочек будет неточным. В 1С:Зарплата и Управление Персоналом используйте параметр Календарь.РабочиеДни.
Почему разница между 1 марта и 1 апреля может быть не 31 день?

Если в расчёте участвует конец месяца, результат зависит от метода вычитания. Например:

- РазностьДат(Дата(2023, 4, 1), Дата(2023, 3, 1), "День") вернёт 31 день.

- Но если использовать ДобавитьМесяц(Дата(2023, 3, 31), 1), результат будет "30.04.2023" (последний день месяца), а разница составит 30 дней!

4. Альтернативные способы вычитания дат

Помимо РазностьДат(), в 1С можно вычитать даты другими методами. Они полезны для специфических задач или когда нужна большая гибкость.

4.1. Ручное вычитание через компоненты даты

Если требуется разложить разницу на годы, месяцы и дни:

Год1 = Год(Дата1); Месяц1 = Месяц(Дата1); День1 = День(Дата1);

Год2 = Год(Дата2); Месяц2 = Месяц(Дата2); День2 = День(Дата2);

// Рассчитываем разницу в годах и месяцах

ЛетРазница = Год2 - Год1;

Если Месяц2 < Месяц1 Или (Месяц2 = Месяц1 И День2 < День1) Тогда

ЛетРазница = ЛетРазница - 1;

КонецЕсли;

4.2. Использование ДобавитьДень() в цикле

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

ДниРазницы = 0;

ТекущаяДата = Дата1;

Пока ТекущаяДата < Дата2 Цикл

Если НЕ ЭтоВыходнойИлиПраздник(ТекущаяДата) Тогда

ДниРазницы = ДниРазницы + 1;

КонецЕсли;

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

КонецЦикла;

⚠️ Внимание: Циклы по датам значительно замедляют выполнение кода, особенно для больших интервалов (например, 10+ лет). Используйте их только если другие методы не подходят.

5. Работа с временными зонами и сервером

В распределённых системах (например, 1С:Предприятие с веб-клиентом или мобильным доступом) даты могут обрабатываться на сервере и клиенте в разных временных зонах. Это приводит к расхождениям при вычитании.

Чтобы избежать ошибок:

  • 🌍 Всегда приводите даты к единой временной зоне перед вычитанием. Используйте УстановитьВременнуюЗону():
  • ⏰ Для точных расчётов (например, в логистике) учитывайте не только дату, но и время. Функция РазностьДат() с параметром "Секунда" поможет:
РазницаВСекундах = РазностьДат(Дата2, Дата1, "Секунда");
НачалоДня(Дата1) = НачалоДня(Дата2)

Это избавит от ошибок из-за разницы во времени (например, "01.01.2023 23:59" и "02.01.2023 00:01").-->

6. Специфика вычитания дат в типовых конфигурациях

Разные конфигурации могут иметь уникальные нюансы при работе с датами. Рассмотрим самые популярные:

Конфигурация Особенности вычитания дат Рекомендации
1С:Бухгалтерия Часто требуется расчёт пени по дням просрочки. Используйте РабочиеДниКалендаряБух(). Для точности настройте Календарь.ПраздничныеДни в справочнике организации.
1С:Зарплата и Управление Персоналом Расчёт стажа, больничных, отпусков. Важно учитывать неполные месяцы. Используйте Календарь.РабочиеДни и ГрафикРаботыСотрудника.
1С:Управление Торговлей Анализ интервалов между заказами, сроки поставок, акции по датам. Для маркетинговой аналитики используйте РазностьДат(..., "Час").

В конфигурациях с модулем "Бюджет и планирование" функция РазностьДат() может возвращать некорректные результаты для дат до 2000 года из-за особенностей хранения исторических данных. Перед работой с архивными датами проверьте настройки периода хранения в конфигураторе.

7. Оптимизация производительности

Вычитание дат в циклах или больших выборках может тормозить систему. Следующие приёмы помогут ускорить код:

  • Кэшируйте результаты: Если одна и та же разница дат используется многократно, сохраните её в переменную.
  • Избегайте циклов: Замените ручной перебор дат на встроенные функции (например, РазностьДат() вместо Пока ... Цикл).
  • Индексируйте поля с датами: В запросах добавьте индексы для полей типа Дата, чтобы ускорить выборку.
// Пример оптимизированного запроса с датами

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| РазностьДат(&ТекущаяДата, ДатаДокумента, ""День"") КАК ДниПросрочки

|ИЗ

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

|ГДЕ

| Заказ.ДатаДокумента < &ТекущаяДата

| И Заказ.Статус = &Статус";

Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());

Запрос.УстановитьПараметр("Статус", Перечисление.СтатусыЗаказов.НеОплачен);

💡

Для максимальной производительности при работе с датами в 1С используйте серверные процедуры и функции. Клиентский код работает медленнее, особенно при больших объёмах данных.

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

Как вычесть из одной даты другую, чтобы получить разницу в часах?

Используйте параметр "Час" в функции РазностьДат():

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

Если нужны часы с учётом минут, преобразуйте секунды:

СекундыРазницы = РазностьДат(Дата2, Дата1, "Секунда");

ЧасыСДробью = СекундыРазницы / 3600;

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

Функция всегда возвращает целое число для единиц измерения "День", "Месяц" или "Год". Если вы получаете дробь, скорее всего:

  • Вы используете "Секунда" или "Минута" как единицу измерения;
  • В датах указано время, и вы не привели их к началу дня (НачалоДня()).
Как посчитать количество рабочих дней между двумя датами?

В типовых конфигурациях (например, 1С:Зарплата) используйте:

РабочиеДни = Календарь.РабочиеДни(Дата1, Дата2);

Для кастомных решений создайте справочник праздников и проверяйте каждый день в цикле:

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

РабочиеДни = РабочиеДни + 1;

КонецЕсли;

Можно ли вычесть из даты число (например, 5 дней)?

Да, но не через вычитание, а с помощью функции ДобавитьДень() с отрицательным значением:

ДатаМинус5Дней = ДобавитьДень(ИсходнаяДата, -5);

Аналогично работают ДобавитьМесяц(), ДобавитьГод().

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

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

Годы  = РазностьДат(Дата2, Дата1, "Год");

ОстатокПослеЛет = ДобавитьГод(Дата1, Годы);

Месяцы = РазностьДат(Дата2, ОстатокПослеЛет, "Месяц");

ОстатокПослеМесяцев = ДобавитьМесяц(ОстатокПослеЛет, Месяцы);

Дни = РазностьДат(Дата2, ОстатокПослеМесяцев, "День");