Вычисление разницы между датами в 1С:Предприятие — одна из самых востребованных операций как для бухгалтеров, так и для разработчиков. Без этого не обойтись при расчёте просроченной задолженности, определении стажа сотрудников, анализе временных интервалов в отчётах или автоматизации бизнес-процессов. Казалось бы, что может быть проще: взять две даты и вычесть одну из другой? Но в 1С этот процесс имеет нюансы, зависящие от версии платформы, типа данных и даже региональных настроек.
В этой статье мы разберём 5 основных способов найти разницу между датами — от элементарных встроенных функций до программных решений для нестандартных задач. Вы узнаете, как получить результат в днях, месяцах или годах, избежать ошибок с високосными годами, а также научитесь работать с временными метками (ДатаВремя). Особое внимание уделим типичным ловушкам, например, когда разница в 31.01.2026 и 01.03.2026 не равна двум месяцам, и как это обойти.
Материал будет полезен и новичкам, и опытным пользователям. Бухгалтеры найдут здесь готовые формулы для отчётов, а разработчики — оптимизированные алгоритмы для обработок. Все примеры тестировались на актуальных версиях платформы 1С:Предприятие 8.3 (включая 8.3.23).
1. Базовый метод: функция РазностьДат()
Самый простой способ получить разницу между двумя датами — использовать встроенную функцию РазностьДат(). Она возвращает количество полных дней между датами, игнорируя время (если оно указано). Синтаксис:
РазностьДат(Дата2, Дата1)
Где Дата2 — более поздняя дата, а Дата1 — более ранняя. Если перепутать порядок, результат будет отрицательным. Пример:
Результат = РазностьДат('2026-03-15', '2026-03-01'); // Вернёт 14
- ✅ Плюсы: максимальная простота, работает во всех версиях 1С, не требует программирования.
- ⚠️ Ограничения: учитывает только дни, не подходит для расчёта месяцев/лет или временных интервалов.
- 📅 Нюанс: если одна из дат содержит время (например,
'2026-03-01 14:30:00'), оно будет проигнорировано.
Этот метод идеален для задач вроде расчёта просрочки платежа или количества дней отпуска. Но что делать, если нужна разница в месяцах или годах? Об этом — в следующем разделе.
2. Разница в месяцах и годах: функция Месяц() и арифметика
Для вычисления разницы в месяцах или годах в 1С нет отдельной функции, но задачу легко решить с помощью арифметических операций. Основной инструмент — функция Месяц(), которая возвращает номер месяца (от 1 до 12), и оператор вычитания для лет.
Формула для месяцев:
РазницаВМесяцах = (Год(Дата2) - Год(Дата1)) * 12 + (Месяц(Дата2) - Месяц(Дата1));
Пример:
Дата1 = '2026-01-15';
Дата2 = '2026-03-20';
Разница = (2026 - 2026) * 12 + (3 - 1); // Вернёт 2
⚠️ Внимание: этот метод даёт приблизительный результат! ЕслиДата1 = '2026-01-31'иДата2 = '2026-03-01', разница составит 2 месяца, хотя фактически прошёл 1 месяц и 1 день. Для точных расчётов используйте метод из раздела 4.
Для разницы в годах используйте аналогичную логику:
РазницаВГодах = Год(Дата2) - Год(Дата1);
Но и здесь есть подводные камни. Например, если сравнивать '2026-12-31' и '2026-01-01', разница в годах будет 1, хотя фактически прошёл всего 1 день. Чтобы учесть это, добавьте проверку:
Если Дата2 < НачалоГода(Дата2) + РазницаВГодах * 365 Тогда
РазницаВГодах = РазницаВГодах - 1;
КонецЕсли;
Убедиться, что даты не пустые
Проверить формат дат (ДД.ММ.ГГГГ)
Учесть високосные годы при расчёте в днях
Сравнить результаты с календарём для критичных задач-->
3. Работа с типом ДатаВремя: учитываем часы и минуты
Если вам нужна разница не только в датах, но и во времени (например, для расчёта продолжительности звонков или рабочих смен), используйте тип данных ДатаВремя. В этом случае функция РазностьДат() вернёт количество секунд между двумя метками.
Пример:
Начало = '2026-03-15 09:00:00';
Конец = '2026-03-15 17:30:00';
Секунды = РазностьДат(Конец, Начало); // Вернёт 30600 (8.5 часов в секундах)
Чтобы преобразовать секунды в часы или минуты, используйте деление:
Часы = Секунды / 3600; // 30600 / 3600 = 8.5
Минуты = (Секунды % 3600) / 60; // Остаток от часов, делённый на 60
| Единица измерения | Формула | Пример результата |
|---|---|---|
| Секунды | РазностьДат(Дата2, Дата1) |
30600 |
| Минуты | РазностьДат(Дата2, Дата1) / 60 |
510 |
| Часы | РазностьДат(Дата2, Дата1) / 3600 |
8.5 |
| Дни | РазностьДат(Дата2, Дата1) / 86400 |
0.354 (8.5 часов) |
Этот метод незаменим для табелей рабочего времени, логистических расчётов или анализа активности пользователей. Однако помните, что при переходе на зимнее/летнее время разница может искажаться на 1 час — этот нюанс важно учитывать в системах с высокой точностью.
4. Точный расчёт с учётом календаря: метод ДобавитьМесяц()
Как мы видели ранее, простая арифметика с месяцами даёт приблизительный результат. Для точного расчёта (например, для начисления процентов по кредиту или определения стажа) используйте цикл с функцией ДобавитьМесяц(). Этот метод учитывает реальное количество дней в каждом месяце.
Алгоритм:
- Инициализируйте счётчик месяцев (
Счётчик = 0). - В цикле добавляйте по одному месяцу к начальной дате, пока она не превысит конечную.
- Увеличивайте счётчик на каждой итерации.
Пример кода:
ДатаНачало = '2026-01-31';
ДатаКонец = '2026-03-01';
Счётчик = 0;
Пока ДатаНачало < ДатаКонец Цикл
ДатаНачало = ДобавитьМесяц(ДатаНачало, 1);
Счётчик = Счётчик + 1;
КонецЦикла;
// Вернёт 1 (а не 2, как в простом вычитании)
Этот способ гарантирует корректный результат даже для краевых случаев вроде 31.01 → 01.03 или 28.02 → 31.03 в високосный год. Однако он требует больше ресурсов, поэтому не подходит для обработки больших массивов данных (например, в отчётах по тысячам документов).
Для ускорения расчётов в больших выборках предварительно отфильтруйте данные по году, а точный подсчёт месяцев применяйте только к релевантным записям.
5. Программные решения: обработки и внешние компоненты
Если стандартные функции 1С не покрывают ваши нужды (например, требуется учитывать рабочие/выходные дни или праздники), придётся писать собственные обработки или подключать внешние компоненты. Рассмотрим два подхода:
5.1. Обработка с учётом рабочих дней
Для расчёта разницы только по рабочим дням (исключая субботу, воскресенье и праздники) создайте функцию с проверкой дня недели:
Функция РабочиеДни(Дата1, Дата2)
Дни = РазностьДат(Дата2, Дата1);
Рабочие = 0;
Для Счётчик = 0 По Дни - 1 Цикл
ТекущаяДата = Дата1 + Счётчик;
Если Не ТекущаяДата.ДеньНедели() В (6, 7) Тогда // 6 и 7 — суббота и воскресенье
Рабочие = Рабочие + 1;
КонецЕсли;
КонецЦикла;
Возврат Рабочие;
КонецФункции;
Чтобы учесть праздники, добавьте проверку через справочник или массив дат:
Если НЕ НайтиСтрока(МассивПраздников, ТекущаяДата) Тогда
Рабочие = Рабочие + 1;
КонецЕсли;
5.2. Внешние компоненты для сложных расчётов
Для комплексных задач (например, расчёт стажа с учётом декретных отпусков или неполных рабочих дней) используйте внешние компоненты:
- 📦 1С:Библиотека стандартных подсистем (БСП): содержит готовые процедуры для работы с датами.
- 🔧 Дополнительные обработки: на Инфостарте или 1С-Галлерее можно найти решения для нестандартных календарей.
- 🌍 API внешних сервисов: например, интеграция с Google Calendar для учёта корпоративных праздников.
⚠️ Внимание: при использовании внешних компонент проверяйте их совместимость с вашей версией платформы 1С:Предприятие. Некоторые решения могут конфликтовать с обновлениями или требовать дополнительных лицензий.
6. Типичные ошибки и как их избежать
Даже опытные пользователи 1С допускают ошибки при работе с датами. Вот самые распространённые ловушки и способы их обойти:
- 🗓️ Пустые даты: если одна из дат не инициализирована (
Дата = '00010101'), функцияРазностьДат()вернёт некорректный результат. Всегда проверяйте даты на заполненность:Если Дата1 = '00010101' Или Дата2 = '00010101' ТогдаПредупреждение("Указана некорректная дата!");
КонецЕсли;
- 🕒 Игнорирование времени: если в датах указано время, но вам нужны только дни, обнулите его:
ДатаБезВремени = НачалоДня(Дата); - 🌐 Региональные настройки: в некоторых странах формат даты отличается от
ДД.ММ.ГГГГ. ИспользуйтеФормат(Дата, "ДЛФ=D")для универсального отображения. - 🔄 Високосные годы: при ручном расчёте дней в году не забудьте про 29 февраля. Для проверки используйте:
Если Год(Дата) % 4 = 0 И (Год(Дата) % 100 <> 0 Или Год(Дата) % 400 = 0) Тогда// Год високосный
КонецЕсли;
Ещё одна частая ошибка — сравнение дат как строк. Например, '01.03.2026' > '28.02.2026' в строковом формате даст Ложь, потому что "01" меньше "28". Всегда преобразуйте строки в тип Дата:
Дата1 = Дата(СтрокаДата1);
Дата2 = Дата(СтрокаДата2);
Почему разница между '31.01.2026' и '01.03.2026' не равна 2 месяцам?
Потому что февраль содержит 28 (или 29) дней. Простое вычитание месяцев (3 - 1 = 2) игнорирует фактическую продолжительность февраля. Точный расчёт требует учёта календарной структуры, как описано в разделе 4.
7. Практическое применение: примеры для бухгалтерии и кадров
Разберём реальные задачи, где вычисление разницы между датами критично для бизнес-процессов.
7.1. Расчёт просроченной дебиторской задолженности
Формула для отчёта:
ПросрочкаДней = РазностьДат(ТекущаяДата(), ДатаОплаты);
Если ПросрочкаДней > 0 Тогда
СуммаПени = СуммаДолга (ПросрочкаДней ПроцентПени / 100);
КонецЕсли;
7.2. Определение стажа сотрудника
Для кадровых отчётов используйте комбинацию методов из разделов 2 и 4:
// Пример для стажа в годах и месяцах
Годы = Год(ТекущаяДата()) - Год(ДатаПриёма);
Месяцы = РазницаВМесяцах(ТекущаяДата(), ДатаПриёма) % 12;
7.3. Контроль сроков исполнения задач
В системах управления проектами:
ОсталосьДней = РазностьДат(Дедлайн, ТекущаяДата());
Если ОсталосьДней < 3 Тогда
Состояние = "Критично";
ИначеЕсли ОсталосьДней < 7 Тогда
Состояние = "Внимание";
Иначе
Состояние = "В норме";
КонецЕсли;
Для автоматизации таких расчётов создайте регламентное задание в 1С, которое будет ежедневно обновлять статусы задач.
Для критичных расчётов (например, начисление пени) всегда дублируйте автоматические результаты ручной проверкой в первые дни после внедрения нового алгоритма.
FAQ: Частые вопросы по работе с датами в 1С
Как получить разницу между датами в часах, если время не указано?
Если у вас есть только даты без времени (например, '15.03.2026'), но нужно посчитать часы, умножьте разницу в днях на 24:
Дни = РазностьДат(Дата2, Дата1);
Часы = Дни * 24;
Но помните, что такой расчёт не учитывает переход на зимнее/летнее время.
Почему функция РазностьДат() возвращает отрицательное число?
Это означает, что первая дата (Дата1) позже второй (Дата2). Поменяйте их местами или используйте Абс():
Результат = Абс(РазностьДат(Дата1, Дата2));
Как посчитать количество полных недель между датами?
Разделите разницу в днях на 7 и округлите вниз:
Недели = Цел(РазностьДат(Дата2, Дата1) / 7);
Можно ли получить разницу в кварталах?
Да, для этого сначала рассчитайте разницу в месяцах (см. раздел 2), затем разделите на 3:
Кварталы = Цел(РазницаВМесяцах / 3);
Обратите внимание, что остаток от деления покажет неполные кварталы.
Как учесть праздничные дни при расчёте рабочих дней?
Создайте справочник с праздничными датами и модифицируйте функцию из раздела 5.1:
Если НЕ ТекущаяДата.ДеньНедели() В (6, 7)
И НЕ Справочник.Праздники.НайтиПоНаименованию(Формат(ТекущаяДата, "ДЛФ=D")) Тогда
Рабочие = Рабочие + 1;
КонецЕсли;