Часто при разработке в 1С возникает типовая, на первый взгляд, задача: есть основная дата и есть вторая дата, хранящая только время (например, 01.01.0001 06:00:00). Как их сложить, чтобы получить исходную дату с добавленным временем? Проанализируем ситуацию: если мы попытаемся использовать прямое сложение через оператор плюс, платформа выдаст ошибку преобразования типов. Рассмотрим подробнее, почему так происходит и как правильно решить эту задачу.
В системе 1С не существует отдельного типа данных для хранения исключительно времени. Тип Дата всегда содержит в себе и календарную дату, и время суток. Внутренне платформа хранит дату как количество секунд, прошедших с начала отсчета — 00:00:00 1 января 0001 года. Выясним причину проблем при сложении: математический плюс переопределен платформой только для сложения даты и числа (секунд), а вот сложение двух дат (Дата + Дата) не имеет математического смысла для системы, поэтому разработчики платформы не реализовали эту операцию напрямую.
Разберем по шагам, как правильно выполнить сложение. Чтобы прибавить к одной дате другую, мы должны извлечь из второй даты количество секунд и прибавить это число к первой дате. Вычитание двух дат в 1С работает отлично и всегда возвращает число — разницу в секундах. Посмотрим на пример, который успешно решает задачу:
Дата3 = Дата1 + (Дата2 - Дата(1,1,1));
В этом примере Дата(1,1,1) — это функция-конструктор, возвращающая пустую дату (1 января 0001 года). Вычитая ее из второй даты, мы получаем точное количество секунд (в нашем случае 6 часов = 21600 секунд), которые затем благополучно прибавляются к основной дате.
Обратите внимание на скобки в формуле. Если написать код без них, система выдаст ошибку:
// Такой код вызовет ошибку преобразования к типу Число
Дата3 = Дата1 + Дата2 - Дата(1,1,1);
Проанализируем ситуацию: платформа вычисляет выражение слева направо. Сначала она пытается выполнить Дата1 + Дата2. Как мы уже знаем, складывать две даты напрямую нельзя. Использование скобок гарантирует, что сначала выполнится вычитание (Дата2 - Дата(1,1,1)), которое вернет число, и только потом произойдет сложение даты и числа.
Рассмотрим еще один нюанс. Вызов функции Дата(1,1,1) требует от системы небольших, но все же вычислительных ресурсов. С точки зрения чистоты кода и производительности лучше использовать строковые литералы дат. Это константы, которые сразу воспринимаются системой без дополнительных вызовов.
// Оптимизированный вариант
Дата3 = Дата1 + (Дата2 - '00010101');
Если во второй переменной может оказаться не пустая дата (не 01.01.0001), а любая произвольная календарная дата, из которой вам нужно извлечь только время, метод с вычитанием константы не сработает корректно. Рассмотрим подробнее универсальный способ:
Секунды = Дата2 - НачалоДня(Дата2);
Дата3 = Дата1 + Секунды;
Функция НачалоДня() отсекает время, оставляя только дату (00:00:00). Вычитая из полной даты начало ее же дня, мы получаем чистое время в секундах, которое затем прибавляем к Дата1.
Если логика задачи сложнее, и нужно прибавлять время выборочно, мы можем извлекать отдельные компоненты. Посмотрим на пример:
Час(), Минута() или Секунда().
ДополнительныеСекунды = (Час(Дата2) * 3600) + (Минута(Дата2) * 60) + Секунда(Дата2);
Дата3 = Дата1 + ДополнительныеСекунды;
Важное примечание: если вам необходимо прибавлять не время (часы/секунды), а месяцы или годы, обычное математическое сложение использовать нельзя, так как количество дней в месяцах и годах (високосных) разное. В таких случаях всегда применяйте встроенную функцию ДобавитьМесяц(). А если требуется решить обратную задачу и получить разницу между датами с учетом високосных лет и представлением в виде текста, можно использовать готовый алгоритм расчета разницы между датами.