Работа с датами — одна из самых частых задач в программировании на платформе 1С:Предприятие. Несмотря на кажущуюся простоту, здесь есть свои нюансы, связанные с тем, как система хранит данные и как она обрабатывает время. В этой статье мы подробно разберем, как вычислить разницу между двумя моментами времени, перевести результат в нужные единицы измерения и на что обратить внимание, чтобы избежать типичных ошибок.
Для начала проанализируем, что представляет собой тип данных Дата в 1С. В системе 1С дата — это не просто числовое значение года, месяца и дня, а совокупность даты и времени с точностью до секунды. Внутри платформы дата хранится как количество секунд, прошедших с начала нашей эры (01.01.0001 00:00:00).
Рассмотрим простейшую операцию вычитания. Если мы вычтем одну дату из другой, результатом всегда будет число секунд. Это фундаментальное правило, от которого мы будем отталкиваться во всех дальнейших расчетах. Выясним это на простом примере:
ДатаНачала = Дата(2023, 10, 01, 10, 00, 00); // 1 октября 2023 года, 10:00
ДатаОкончания = Дата(2023, 10, 01, 10, 05, 00); // 1 октября 2023 года, 10:05
РазницаВСекундах = ДатаОкончания - ДатаНачала;
// Результат будет равен 300 (5 минут * 60 секунд)
Поскольку результат вычитания — это секунды, для получения более крупных единиц измерения нам потребуется простая арифметика. Разберем по шагам, как получить привычные нам значения:
Посмотрим на практическую реализацию функции, которая вычисляет разницу в днях:
Функция РазницаВДнях(Дата1, Дата2)
// Вычисляем разность и делим на количество секунд в сутках
Разность = (Дата2 - Дата1) / 86400;
// Если нам нужно целое количество дней, используем Цел()
Возврат Цел(Разность);
КонецФункции
Важный нюанс: Если в ваших переменных ДатаС и ДатаПо присутствует время, простая математическая операция может вернуть дробное число (например, 1.5 дня). Если ваша задача — посчитать количество календарных дней, прошедших между датами, независимо от времени, обязательно используем функцию НачалоДня() для обеих переменных перед вычитанием.
РазностьКалендарныхДней = (НачалоДня(ДатаПо) - НачалоДня(ДатаС)) / 86400;
Если вы работаете в современной конфигурации (например, УТ 11, ERP 2 или Бухгалтерия 3.0), нет необходимости изобретать велосипед. Проанализируем возможности программного модуля ОбщегоНазначенияКлиентСервер. В нем уже содержатся готовые инструменты для работы с датами.
Рассмотрим функции, которые могут быть полезны:
РазностьДагВКалендарныхДнях — позволяет получить чистую разницу без учета времени.РазностьДагВМесяцах — корректно вычисляет количество полных месяцев, что математически сделать сложнее из-за разного количества дней в феврале или августе.Использование типовых методов гарантирует, что ваш код будет легче поддерживать, а сложные случаи (например, переход через високосный год) будут обработаны корректно. Для комплексного расчета интервалов с учетом високосных лет и выводом результата в виде текста можно использовать готовое решение для расчета разницы дат и формирования строкового представления.
Рассмотрим более сложную ситуацию, затронутую в обсуждении: что делать, если разница между датами равна нулю, но объекты созданы в разное время? В 1С тип Дата ограничен точностью в 1 секунду. Миллисекунды в стандартном реквизите документа не хранятся.
Для определения последовательности событий в пределах одной секунды используется объект МоментВремени. Он объединяет в себе Дата и Ссылка. Проанализируем, как это работает:
В современных версиях платформы 8.3 (начиная с 8.3.3) используется механизм Sequential GUID. Это означает, что ссылки, создаваемые одна за другой, обычно имеют возрастающее значение. Поэтому документы одного типа, записанные в одну и ту же секунду, в большинстве случаев выстроятся в порядке их физического создания.
При расчете разницы дат мы можем столкнуться с критической ошибкой, если одна из дат не заполнена. Выясним причину: пустая дата в 1С соответствует значению 01.01.0001 00:00:00. Если вы вычтете пустую дату из текущей, вы получите колоссальное число секунд, которое может нарушить логику всей программы (например, при расчете пени или сроков доставки).
Всегда добавляйте проверку перед расчетом:
Если ЗначениеЗаполнено(ДатаС) И ЗначениеЗаполнено(ДатаПо) Тогда
Разница = (ДатаПо - ДатаС) / 86400;
Иначе
Разница = 0;
Сообщить("Одна из дат не заполнена!");
КонецЕсли;
Хотя автор вопроса просил решение для обычной функции, кратко сравним это с поведением в запросах. В языке запросов 1С существует функция РАЗНОСТЬДАТ(Дата1, Дата2, Тип).
Будьте внимательны: функция РАЗНОСТЬДАТ в запросе считает количество границ периодов. Это означает, что разница в днях между 23:59:59 одного дня и 00:00:01 следующего дня будет равна 1, хотя фактически прошло всего 2 секунды. В коде же (через вычитание) вы получите честный результат в секундах, который в данном примере будет близок к нулю.
Подведем итоги нашего анализа. Для получения разницы дат во встроенном языке:
НачалоДня(), если время не должно влиять на результат.ЗначениеЗаполнено().Используя эти правила, вы сможете корректно вычислять любые временные интервалы и обеспечите стабильную работу ваших алгоритмов в любых бизнес-процессах.