Расчет количества дней между двумя датами — одна из самых частых задач в . Она возникает при работе с графиками, сроками оплаты, отчетными периодами, отпусками и многими другими бизнес-процессами. Казалось бы, что может быть проще? Но на практике даже опытные разработчики сталкиваются с нюансами: нужно ли учитывать выходные, как обрабатывать неполные дни, что делать с временными зонами или как избежать ошибок при переходе на зимнее/летнее время.

В этой статье мы разберем 5 рабочих способов посчитать дни между датами в 1С:Предприятие 8.3/8.2, от элементарных встроенных функций до сложных алгоритмов с учетом производственного календаря. Каждый метод проиллюстрирован реальными примерами кода, которые вы сможете сразу использовать в своих конфигурациях — будь то УТ 11, БП 3.0, ЗУП 3.1 или ERP 2.5.

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

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

1. Самый простой способ: функция РазностьДат

Начнем с базового метода, который подходит для 90% задач. В есть встроенная функция РазностьДат, которая возвращает разницу между двумя датами в заданных единицах измерения. Для подсчета дней используем параметр "День".

Синтаксис функции:

РазностьДат(КонечнаяДата, НачальнаяДата,"День")

Пример 1. Рассчитаем количество дней между 1 января и 10 января 2026 года:

КоличествоДней = РазностьДат('20260110','20260101',"День");

// Результат: 9

Пример 2. Если нужно посчитать дни между текущей датой и какой-либо прошлой датой:

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

ПрошлаяДата ='20231201';

КоличествоДней = РазностьДат(ТекущаяДата, ПрошлаяДата,"День");

Плюсы метода:

  • 🔹 Простота — одна строка кода
  • 🔹 Работает во всех конфигурациях 1С без дополнительных настроек
  • 🔹 Учитывает високосные годы автоматически

Ограничения:

  • 🚫 Не учитывает выходные и праздничные дни
  • 🚫 Не работает с временными метками (только даты без времени)
  • 🚫 Не подходит для расчета рабочего времени
💡

Если вам нужно посчитать дни между датами с учетом времени (например, 10:00 01.01.2026 и 14:30 02.01.2026), используйте функцию РазностьДат с параметром "Секунда", а затем конвертируйте результат в дни, разделив на 86400 (количество секунд в сутках).

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

В даты можно вычитать друг из друга напрямую — результат будет в днях. Этот способ еще проще, чем РазностьДат, но имеет свои нюансы.

Пример:

Дата1 ='20260315';

Дата2 ='20260320';

КоличествоДней = Дата2 - Дата1;

// Результат: 5

🔍 Важная особенность: если вычитать даты в обратном порядке (более раннюю из поздней), результат будет отрицательным. Это можно использовать для проверки корректности введенных дат:

Если ДатаОкончания < ДатаНачала Тогда

Сообщить("Дата окончания раньше даты начала!");

КонецЕсли;

⚠️ Внимание: при вычитании дат с временем (тип ДатаВремя) результат будет в долях дня. Например, разница между '20260101 12:00:00' и '20260101 00:00:00' составит 0.5 (полдня).

📌 Когда использовать этот метод:

  • 📅 Для быстрых расчетов в отчетах или обработках
  • 🔄 Когда нужно проверить логическую последовательность дат
  • ⚡ Для операций с большими массивами данных (вычитание работает быстрее, чем РазностьДат)
📊 Какой метод расчета дней вы используете чаще?
Функция РазностьДат
Вычитание дат
Запросы к базе
Собственные функции
Другой вариант

3. Расчет дней с учетом рабочего календаря

Если вам нужно посчитать только рабочие дни (исключая выходные и праздники), стандартные функции 1С не подойдут. Здесь потребуется использовать ПроизводственныйКалендарь — объект, который есть в большинстве типовых конфигураций (ЗУП, ERP, БП).

Пример кода для расчета рабочих дней:

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

ДатаНачала ='20260101';

ДатаОкончания ='20260131';

// Получаем количество рабочих дней в периоде

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

📊 Сравнение методов:

Метод Учитывает выходные Учитывает праздники Требует доработок
РазностьДат ❌ Нет ❌ Нет ❌ Нет
Вычитание дат ❌ Нет ❌ Нет ❌ Нет
ПроизводственныйКалендарь ✅ Да ✅ Да ⚠️ Только в типовых конфигурациях
Собственная функция ✅ Да ✅ Да ✅ Требует разработки

⚠️ Внимание: в нетиповых конфигурациях объекта ПроизводственныйКалендарь может не быть. В этом случае придется создавать свой календарь с учетом выходных или интегрироваться с внешними сервисами (например, через HTTP-запросы к государственным календарям праздников).

🔹 Как быть, если нет ПроизводственногоКалендаря?

  • 📌 Создать справочник с праздничными датами и проверять попадание в него
  • 📌 Использовать внешнюю обработку с готовым календарем
  • 📌 Написать функцию, которая будет пропускать субботу и воскресенье
Пример функции для расчета рабочих дней без ПроизводственногоКалендаря

Функция КоличествоРабочихДней(ДатаНачала, ДатаОкончания)

ТекущаяДата = ДатаНачала;

Счетчик = 0;

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

ДеньНедели = ДеньНедели(ТекущаяДата);

Если НЕ (ДеньНедели = 6 ИЛИ ДеньНедели = 7) Тогда // Пропускаем субботу и воскресенье

Счетчик = Счетчик + 1;

КонецЕсли;

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

КонецЦикла;

Возврат Счетчик;

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

4. Расчет дней через запросы к базе данных

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

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

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

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

"ВЫБРАТЬ

| Документ.Ссылка КАК Ссылка,

| РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА, Документ.Дата, ДЕНЬ) КАК ДнейПрошло

|ИЗ

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

|ГДЕ

| Документ.Дата > ДАТАВРЕМЯ(2026, 1, 1)";

Пример 2. Запрос с группировкой по периодам (например, посчитать количество дней между датой создания и датой оплаты для каждого заказа):

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

"ВЫБРАТЬ

| Заказ.Ссылка КАК Заказ,

| МАКСИМУМ(ВЫБОР

| КОГДА Заказ.ДатаОплаты ЕСТЬ NULL

| ТОГДА 0

| ИНАЧЕ РАЗНОСТЬДАТ(Заказ.ДатаОплаты, Заказ.Дата, ДЕНЬ)

| КОНЕЦ) КАК ДнейДоОплаты

|ИЗ

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

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

| Заказ.Ссылка";

💡 Советы по оптимизации запросов:

  • 🔧 Используйте ИНДЕКСИРОВАТЬ ПО для полей с датами, если запрос работает медленно
  • 🔧 Избегайте вычислений в ГДЕ — переносите их в ВЫБРАТЬ
  • 🔧 Для больших баз разбейте запрос на части с помощью ОБЪЕДИНИТЬ

⚠️ Внимание: в запросах функция РАЗНОСТЬДАТ работает иначе, чем встроенная функция РазностьДат! Например, РАЗНОСТЬДАТ('20260110','20260101', ДЕНЬ) вернет 9, а РазностьДат('20260110','20260101',"День") — тоже 9. Но если поменять даты местами, результат будет разным: запрос вернет отрицательное число, а функция — положительное.

🔹 Убедитесь, что поля с датами проиндексированы

🔹 Проверьте, что в выборке нет NULL-значений для дат

🔹 Ограничьте период выборки (например, за последний год)

🔹 Протестируйте запрос на небольшом объеме данных-->

5. Учет временных зон и летнего/зимнего времени

Если ваша база работает с клиентами или филиалами в разных часовых поясах, при расчете дней между датами могут возникать ошибки. Например, разница между '20260331 23:00:00' и '20260401 01:00:00' в Москве и Екатеринбурге будет разной из-за перехода на летнее время.

Как решить проблему:

  1. 🌍 Приведите все даты к одному часовому поясу с помощью функции ЧасовойПояс:
ДатуМск = ЧасовойПояс(ДатуСЧасовымПоясом,"Europe/Moscow");
  1. 🕒 Используйте тип ДатаВремя вместо Дата, если важно время:
РазницаВоВремени = Дата2 - Дата1; // Результат в днях (может быть дробным)

РазницаВДнях = Цел(РазницаВоВремени); // Округляем до целых дней

📌 Таблица часовых поясов в 1С:

Часовый пояс Идентификатор в 1С Смещение от UTC
Москва "Europe/Moscow" UTC+3
Екатеринбург "Asia/Yekaterinburg" UTC+5
Новосибирск "Asia/Novosibirsk" UTC+7
Владивосток "Asia/Vladivostok" UTC+10

⚠️ Внимание: при работе с временными зонами учитывайте, что переход на летнее/зимнее время в разных странах происходит в разные даты. Например, в России с 2014 года переход отменен, а в Европе он все еще действует. Это может привести к расхождению в 1 час при расчетах.

🔹 Как избежать ошибок:

  • 🕐 Храните все даты в базе в UTC, а преобразовывайте в локальное время только при отображении
  • 🕐 Используйте функцию ЛокальнаяДата для приведения к текущему поясу пользователя
  • 🕐 Проверяйте настройки часовых поясов в Администрирование → Настройки программы
💡

При расчете дней между датами с временем всегда приводите их к одному часовому поясу или используйте UTC. Это избавит от ошибок при переходе на летнее/зимнее время и работе с распределенными базами.

6. Сложные случаи: неполные дни, округление, календарные особенности

Иногда требуется не просто посчитать дни, а решить более сложные задачи:

  • 📅 Неполные дни: например, если событие началось в 14:00 01.01.2026 и закончилось в 10:00 02.01.2026, нужно ли считать это как 1 день или 2?
  • 🔄 Округление: если разница составила 1.6 дня, округлять до 1 или 2?
  • 🎭 Календарные особенности: например, в исламском календаре длительность месяцев разная.

Пример 1. Округление дней в большую сторону (например, для расчета пеней):

Разница = ДатаОкончания - ДатаНачала;

КоличествоДней = Окр(Разница, 0); // Округление до целых

// Или

КоличествоДней = Цел(Разница) +?(Разница - Цел(Разница) > 0, 1, 0); // Округление вверх

Пример 2. Учет только полных дней (игнорируем время):

ДатаНачалаБезВремени = НачалоДня(ДатаНачала);

ДатаОкончанияБезВремени = НачалоДня(ДатаОкончания) + 86400; // +1 день для включения конечной даты

КоличествоПолныхДней = ДатаОкончанияБезВремени - ДатаНачалаБезВремени;

Критичный нюанс: при расчете дней для юридически значимых документов (например, сроков оплаты по договору) всегда уточняйте в нормативных актах, как именно считаются дни: календарные или рабочие, включаются ли праздники, как округляются неполные сутки. Например, по ст. 193 ГК РФ последний день срока истекает в 24:00, а если это выходной — переносится на следующий рабочий день.

🔹 Чек-лист для сложных расчетов:

🔹 Уточните, нужно ли учитывать время (или только даты)

🔹 Определите правила округления (вверх, вниз, к ближайшему)

🔹 Проверьте, влияют ли на расчет праздники/выходные

🔹 Убедитесь, что часовой пояс учтен корректно-->

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

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

🔴 Ошибка 1. Использование функции ДеньГода для расчета разницы:

// НЕПРАВИЛЬНО!

День1 = ДеньГода(Дата1);

День2 = ДеньГода(Дата2);

Разница = День2 - День1; // Ошибка, если даты в разных годах!

Решение: используйте РазностьДат или вычитание дат.

🔴 Ошибка 2. Игнорирование NULL-значений:

// НЕПРАВИЛЬНО - вылетит ошибка, если ДатаОкончания не заполнена

Разница = ДатаОкончания - ДатаНачала;

Решение: всегда проверяйте заполненность дат:

Если ДатаОкончания ='00010101' ИЛИ ДатаНачала ='00010101' Тогда

Возврат 0;

КонецЕсли;

🔴 Ошибка 3. Неучет переходов через полночь при работе с ДатаВремя:

// НЕПРАВИЛЬНО - может дать неверный результат при переходе через 00:00

РазницаВДнях = Цел((ДатаОкончания - ДатаНачала) / 86400);

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

📌 Как тестировать код с датами:

  • 🧪 Проверяйте граничные случаи: переход через полночь, конец месяца, високосный год
  • 🧪 Тестируйте с пустыми датами ('00010101')
  • 🧪 Сравнивайте результаты с ручным подсчетом в календаре
💡

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

FAQ: Ответы на частые вопросы

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

Используйте функцию РазностьДат с параметром "Неделя":

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

Если нужно учитывать только полные недели (7 дней), используйте:

ПолныхНедель = Цел(РазностьДат(Дата2, Дата1,"День") / 7);
Можно ли посчитать дни между датами в отчете без программирования?

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

  1. Откройте настройки отчета
  2. Добавьте новое поле типа"Выражение"
  3. Введите формулу: РАЗНОСТЬДАТ(ДатаОкончания, ДатаНачала, ДЕНЬ)

Если такого поля нет, обратитесь к администратору 1С для доработки отчета.

Как посчитать дни между датами в управленческом учете (ERP 2)?

В ERP 2.5 для расчета дней между датами документов можно:

  • Использовать стандартные отчеты с группировкой по периодам
  • Создать внешнюю обработку с нужной логикой
  • Добавить вычисляемое поле в динамический список через УправлениеДинамическимСписком

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

Почему РазностьДат возвращает неверное количество дней для исторических дат?

Это связано с тем, что в даты до 1900 года обрабатываются некорректно из-за особенностей григорианского календаря. Для исторических расчетов:

  • Используйте внешние библиотеки для работы с датами
  • Преобразуйте даты влианский формат перед расчетом
  • Ограничьте период расчетов датами после 1900 года
Как посчитать дни между датами в мобильном приложении 1С?

В мобильной платформе 1С:Предприятие доступны те же функции:

// В мобильном клиенте

КоличествоДней = РазностьДат(Дата2, Дата1,"День");

Ограничения:

  • Нет доступа к ПроизводственномуКалендарю (придется реализовывать свой)
  • Запросы работают медленнее, чем на сервере

Рекомендация: переносите сложные расчеты на сервер через ВыполнитьНаСервере.