Расчет разницы между датами — одна из самых частых задач при работе с 1С:Предприятие 8.3. Без этого не обойтись при формировании отчетов по срокам оплаты, анализе просроченных задолженностей, расчете стажа сотрудников или планировании производственных процессов. Казалось бы, что может быть проще: взять две даты и вычесть одну из другой? Но в 1С этот процесс имеет нюансы, которые могут поставить в тупик даже опытного разработчика.
Проблема в том, что платформа 1С предлагает несколько способов работы с датами — от встроенных функций до SQL-запросов, и каждый метод возвращает результат в разных форматах: дни, секунды, месяцы или даже в виде интервалов. Выбор неправильного подхода может привести к ошибкам в расчетах, особенно когда речь идет о календарных периодах (например, разница в месяцах с учетом неполных периодов). В этой статье мы разберем 5 рабочих методов расчета разницы дат в 1С, их плюсы и минусы, а также типичные ошибки, которые допускают программисты.
1. Встроенная функция РазностьДат() — простой способ для большинства задач
Самый очевидный и часто используемый метод — функция РазностьДат(). Она возвращает разницу между двумя датами в заданных единицах измерения: днях, часах, минутах или секундах. Синтаксис функции:
РазностьДат(Дата2, Дата1, ЕдиницаИзмерения)
Где ЕдиницаИзмерения может принимать значения:
- 📅
"Д"— дни (значение по умолчанию) - ⏰
"Ч"— часы - ⏱️
"М"— минуты - ⏳
"С"— секунды
Пример использования:
ДатаНачала = '2026-01-15';
ДатаОкончания = '2026-02-20';
РазницаВДнях = РазностьДат(ДатаОкончания, ДатаНачала); // Вернет 36
⚠️ Внимание: ФункцияРазностьДат()не учитывает рабочие/выходные дни. Если вам нужна разница в рабочих днях, потребуется дополнительная логика или функцияРабочиеДниМеждуДатами()из стандартных библиотек.
Преимущества метода:
- 🔹 Простота и читаемость кода
- 🔹 Быстрое выполнение (встроенная функция платформы)
- 🔹 Поддержка всех основных единиц времени
Однако у этого способа есть ограничения:
- 🚫 Нельзя получить разницу в месяцах или годах напрямую
- 🚫 Не учитываются временные зоны (если даты в разных часовых поясах)
- 🚫 Для сложных календарных расчетов (например, "2 месяца и 5 дней") потребуется комбинировать с другими функциями
2. Использование запросов — когда данные хранятся в базе
Если даты хранятся в базе данных (например, в регистрах сведений или документах), удобнее рассчитывать разницу прямо в запросе 1С. Это позволит избежать лишних обращений к базе и ускорить выполнение кода. В языке запросов 1С для этого есть функция РАЗНОСТЬДАТ().
Пример запроса для расчета количества дней между датой документа и текущей датой:
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка,
РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА(), Документ.Дата, ДЕНЬ) КАК ДнейПрошло
ИЗ
Документ.ЗаказПокупателя КАК Документ
Особенности работы с запросами:
- 📊 Можно сразу отфильтровать результаты (например, выбрать документы, где разница больше 30 дней)
- 🔄 Поддерживаются все те же единицы измерения, что и в
РазностьДат() - 📈 Результаты можно группировать и агрегировать (например, посчитать среднюю просрочку по контрагентам)
| Единица измерения в запросе | Синтаксис | Пример результата |
|---|---|---|
| Дни | ДЕНЬ |
36 |
| Часы | ЧАС |
864 |
| Минуты | МИНУТА |
51840 |
| Секунды | СЕКУНДА |
3110400 |
⚠️ Внимание: В некоторых конфигурациях (особенно старых версиях) функция РАЗНОСТЬДАТ() может работать медленнее, чем вычисления в программном коде. Если запрос выполняется долго, попробуйте перенести логику расчета в модуль объекта.
Когда стоит использовать запросы:
- 🗃️ Нужно получить разницу дат для большого количества записей (тысячи строк)
- 🔍 Требуется отфильтровать или сгруппировать данные по временным интервалам
- 📊 Нужно интегрировать расчеты с другими полями из базы (например, сумма документа + количество дней просрочки)
Проверьте формат хранения дат в базе (Дата или ДатаВремя)
Убедитесь, что временная зона одинакова для всех сравниваемых дат
Определите единицу измерения заранее (дни, часы и т.д.)
Тестируйте запрос на небольшом наборе данных перед выполнением на всей базе-->
3. Программный расчет с учетом календарных периодов
Если вам нужно получить разницу в месяцах или годах, а также учитывать неполные периоды (например, "2 месяца и 15 дней"), стандартные функции 1С не подойдут. В этом случае придется писать собственный код. Вот универсальная функция для расчета разницы в месяцах:
Функция РазницаВМесяцах(ДатаНачала, ДатаОкончания)
Месяцев = (Год(ДатаОкончания) - Год(ДатаНачала)) * 12 + (Месяц(ДатаОкончания) - Месяц(ДатаНачала));
Если День(ДатаОкончания) < День(ДатаНачала) Тогда
Месяцев = Месяцев - 1;
КонецЕсли;
Возврат Месяцев;
КонецФункции
Пример использования:
ДатаТрудоустройства = '2020-05-15';
ТекущаяДата = ТекущаяДата();
Сообщить("Стаж: " + РазницаВМесяцах(ДатаТрудоустройства, ТекущаяДата) + " месяцев");
Для более точного расчета с учетом дней можно модифицировать функцию:
Процедура РазницаПериодов(Дата1, Дата2, Перем Месяцы, Перем Дни)
Месяцы = РазницаВМесяцах(Дата1, Дата2);
Дни = День(Дата2) - День(Дата1);
Если Дни < 0 Тогда
Дни = Дни + ДнейВМесяце(Год(Дата2), Месяц(Дата2) - 1);
КонецЕсли;
КонецПроцедуры
Где ДнейВМесяце() — стандартная функция 1С, возвращающая количество дней в указанном месяце.
Как учитывать високосные годы в расчетах
При расчете разницы в годах или месяцах високосные годы учитываются автоматически в стандартных функциях 1С (например, ДнейВМесяце() вернет 29 для февраля 2026 года). Однако если вы пишете собственную логику для работы с датами, не забывайте проверять год на високосность с помощью функции ГодВисокосный().
Когда нужен программный расчет:
- 📅 Требуется разница в месяцах/годах с учетом неполных периодов
- 🔄 Нужно учитывать специфические бизнес-правила (например, "квартал считается полным, если прошло хотя бы 45 дней")
- 📊 Необходимо интегрировать расчеты с другими алгоритмами (например, начисление премий по стажу)
4. Работа с интервалами времени (Тип "Интервал")
В 1С:Предприятие 8.3 есть специальный тип данных Интервал, который предназначен для хранения временных промежутков. Его удобно использовать, когда нужно не просто получить разницу в днях, а сохранить ее для дальнейших операций (например, сложение интервалов).
Пример создания интервала:
Дата1 = '2026-01-01 10:00:00';
Дата2 = '2026-01-03 15:30:00';
Интервал = Дата2 - Дата1; // Автоматически создаст объект типа "Интервал"
С интервалами можно выполнять следующие операции:
- 🔢 Получать отдельные компоненты (дни, часы, минуты) через свойства
Дни,Часы,Минуты,Секунды - ➕ Складывать и вычитать интервалы
- ⏱️ Преобразовывать в секунды для точных расчетов
Пример работы с интервалом:
Интервал = ДатаОкончания - ДатаНачала;
Дней = Интервал.Дни;
Часов = Интервал.Часы;
Сообщить(Строка(Дней) + " дней и " + Строка(Часов) + " часов");
⚠️ Внимание: При вычитании дат с типомДата(без времени) результат все равно будет иметь типИнтервал, но свойстваЧасы,МинутыиСекундыбудут равны нулю. Если вам нужны только дни, используйтеРазностьДат()— это эффективнее.
Преимущества работы с интервалами:
- 🔹 Точность до секунды
- 🔹 Удобство для сложных временных расчетов (например, суммирование времени выполнения задач)
- 🔹 Возможность конвертации в разные единицы измерения
Дни = Окр(Интервал.ВСекундах() / 86400, 0, 1)
где 1 в конце означает округление вверх.-->
5. Стандартные процедуры из библиотек 1С
Для типовых задач (например, расчет рабочих дней или разница с учетом производственного календаря) не нужно изобретать велосипед — в 1С есть готовые процедуры в стандартных библиотеках:
- 📅
РабочиеДниМеждуДатами()— возвращает количество рабочих дней между двумя датами (учитывает выходные и праздники) - 📊
ДобавитьМесяц()/ДобавитьГод()— удобно для расчета дат с учетом календарных периодов - ⏳
НайтиДатуПоДнюНедели()— помогает найти ближайший понедельник/пятницу и т.д.
Пример использования РабочиеДниМеждуДатами():
КоличествоРабочихДней = РабочиеДниМеждуДатами('2026-01-01', '2026-01-31');
Сообщить("Рабочих дней в январе: " + КоличествоРабочихДней);
Где искать эти функции:
- 📂 В стандартных модулях конфигурации (например,
ОбщийМодуль.РаботаСДатами) - 📦 В типовой конфигурации "Зарплата и управление персоналом" (модуль
Календарь) - 🔧 В библиотеке стандартных подсистем (БСП) для 1С:Предприятие 8.3
⚠️ Внимание: Состав стандартных библиотек может отличаться в зависимости от версии платформы и конфигурации. Если функции нет в вашей базе, проверьте наличие обновлений или реализуйте аналогичную логику самостоятельно.
Когда стоит использовать стандартные процедуры:
- 🏢 Работаете с типовой конфигурацией (УТ, ERP, ЗУП и т.д.)
- 📅 Нужно учитывать производственный календарь (праздники, переносы выходных)
- 🔄 Требуется сложная логика работы с датами (например, "найти последний рабочий день месяца")
Для расчета рабочих дней всегда используйте стандартные функции из библиотек 1С — они учитывают региональные особенности календаря (например, перенос выходных в России).
Типичные ошибки и как их избежать
Даже опытные разработчики 1С иногда допускают ошибки при работе с датами. Вот самые распространенные из них:
- 🚫 Игнорирование временной зоны: Если в базе хранятся даты с временем (тип
ДатаВремя), но без указания временной зоны, расчеты могут быть неточными при работе с распределенными системами. - 🚫 Путаница с форматами дат: Функция
РазностьДат()ожидает параметры типаДата, а не строку. Если передать строку (например,'2026.01.15'), получите ошибку. - 🚫 Неучет граничных условий: При расчете разницы в месяцах легко забыть про случаи, когда день окончания меньше дня начала (например, с 31 января по 28 февраля).
- 🚫 Избыточные вычисления: Расчет разницы в секундах для тысяч записей может замедлить работу системы. В таких случаях лучше использовать запросы.
Как избежать ошибок:
- 🔍 Всегда проверяйте типы передаваемых данных (используйте
ТипЗнч()) - 📅 Тестируйте код на граничных датах (конец месяца, високосные годы)
- ⏱️ Для критичных расчетов добавьте отладочный вывод (например,
Сообщить(ТипЗнч(ДатаНачала)))
FAQ: Частые вопросы по расчету дат в 1С
Как рассчитать разницу между датами с учетом только рабочих дней?
Используйте стандартную функцию РабочиеДниМеждуДатами() из библиотеки 1С. Если ее нет в вашей конфигурации, реализуйте собственную логику с учетом выходных (обычно суббота и воскресенье) и праздничных дней (храните их в справочнике). Пример:
Функция РабочиеДни(Дата1, Дата2)
Дней = РазностьДат(Дата2, Дата1, "Д");
РабочихДней = 0;
ТекущаяДата = НачалоДня(Дата1);
Пока ТекущаяДата <= КонецДня(Дата2) Цикл
Если НЕ ТекущаяДата.ДеньНедели() = 6 И НЕ ТекущаяДата.ДеньНедели() = 7 Тогда
РабочихДней = РабочихДней + 1;
КонецЕсли;
ТекущаяДата = ТекущаяДата + 86400; // +1 день
КонецЦикла;
Возврат РабочихДней;
КонецФункции
Почему РазностьДат() возвращает неверное количество дней?
Наиболее вероятные причины:
- Вы передаете даты в неправильном порядке (должно быть
РазностьДат(БольшаяДата, МеньшаяДата)). - Одна из дат имеет тип
ДатаВремя, а время влияет на результат (используйтеНачалоДня()для обнуления времени). - В вашей конфигурации переопределена стандартная функция (проверьте глобальные модули).
Чтобы диагностировать проблему, выведите типы и значения дат перед расчетом:
Сообщить(ТипЗнч(Дата1) + " | " + Дата1);
Сообщить(ТипЗнч(Дата2) + " | " + Дата2);
Как получить разницу в годах с учетом месяцев?
Стандартных функций для этого нет, поэтому нужно писать собственный код. Вот пример функции, которая возвращает разницу в годах, месяцах и днях:
Процедура РазницаВГодахМесяцахДнях(Дата1, Дата2, Перем Годы, Перем Месяцы, Перем Дни)
Годы = Год(Дата2) - Год(Дата1);
Если Месяц(Дата2) < Месяц(Дата1) Или (Месяц(Дата2) = Месяц(Дата1) И День(Дата2) < День(Дата1)) Тогда
Годы = Годы - 1;
КонецЕсли;
Месяцы = Месяц(Дата2) - Месяц(Дата1);
Если День(Дата2) < День(Дата1) Тогда
Месяцы = Месяцы - 1;
КонецЕсли;
Если Месяцы < 0 Тогда
Месяцы = Месяцы + 12;
КонецЕсли;
Дни = День(Дата2) - День(Дата1);
Если Дни < 0 Тогда
Дни = Дни + ДнейВМесяце(Год(Дата2), Месяц(Дата2) - 1);
КонецЕсли;
КонецПроцедуры
Пример использования:
ДатаРождения = '1990-05-15';
ТекущаяДата = ТекущаяДата();
РазницаВГодахМесяцахДнях(ДатаРождения, ТекущаяДата, Годы, Месяцы, Дни);
Сообщить(Строка(Годы) + " лет, " + Строка(Месяцы) + " месяцев, " + Строка(Дни) + " дней");
Можно ли в 1С рассчитать разницу между датами с точностью до миллисекунд?
Нет, платформа 1С:Предприятие 8.3 не поддерживает миллисекунды. Максимальная точность — до секунд (тип ДатаВремя). Если вам нужна более высокая точность, придется хранить время отдельно (например, в числовом поле) и обрабатывать его вручную.
Альтернативный вариант — использовать внешние системы (например, базы данных с поддержкой миллисекунд) и интегрировать их с 1С через HTTP-Сервисы или COM-соединение.
Как рассчитать количество полных месяцев между датами?
Для этого можно использовать следующую функцию:
Функция ПолныхМесяцевМеждуДатами(Дата1, Дата2)
Возврат (Год(Дата2) - Год(Дата1)) * 12 + (Месяц(Дата2) - Месяц(Дата1)) -
Если День(Дата2) < День(Дата1) Тогда 1 Иначе 0 КонецЕсли;
КонецФункции
Пример:
ДатаНачала = '2026-01-15';
ДатаОкончания = '2026-03-10';
Сообщить("Полных месяцев: " + ПолныхМесяцевМеждуДатами(ДатаНачала, ДатаОкончания)); // Вернет 1