При пакетной обработке или исправлении хронологии документов нередко возникает задача переместить документ в самый конец суток — например, выставить точное время 23:59:50. Разберем, какими математическими функциями платформы 1С это делается правильнее всего, а также рассмотрим важные последствия изменения даты для движений регистров и последовательностей.
Платформа 1С хранит значения типа Дата в секундах. Это позволяет легко манипулировать временем с помощью простых арифметических операций сложения и вычитания секунд относительно начала или конца суток.
Способ 1. Смещение от начала дня (рекомендуемый)
В одних сутках содержится 86 400 секунд. Время 23:59:50 наступает ровно через 86 390 секунд от полуночи (23 часа * 3600 + 59 минут * 60 + 50 секунд = 82800 + 3540 + 50 = 86390). Посмотрим на пример кода:
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокОбъект.Дата = НачалоДня(ДокОбъект.Дата) + 86390;
ДокОбъект.Записать();
Способ 2. Смещение от конца дня
Функция КонецДня() возвращает дату с временем 23:59:59. Чтобы получить 23:59:50, достаточно отнять 9 секунд от конца дня:
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокОбъект.Дата = КонецДня(ДокОбъект.Дата) - 9;
ДокОбъект.Записать();
Почему не стоит использовать строковые преобразования
Использование конструкций вида Дата(Формат(...) + " 23:59:50") работает медленнее, требует лишних преобразований типов и может зависеть от региональных настроек сеанса или формата даты, поэтому прямое сложение секунд через НачалоДня() является более надежным стандартом разработки.
Проанализируем ключевой нюанс: если документ уже проведен, простая смена реквизита Дата и вызов метода Записать() в режиме обычной записи не обновляет период в существующих движениях регистров накопления, сведений или бухгалтерии. Документ будет отображаться проведенным на новое время, но его фактические проводки останутся на старом моменте времени.
Для корректной обработки таких ситуаций рассмотрим возможные варианты действий:
РежимЗаписиДокумента.Проведение. В этом случае платформа автоматически актуализирует даты во всех наборах записей.Период и записать наборы.Объединим вычисление времени, проверку статуса проведения и обработку ошибок в единый алгоритм для обхода выборки документов:
Выборка = Документы.РеализацияТоваровУслуг.Выбрать(ДатаНачала, ДатаОкончания);
Пока Выборка.Следующий() Цикл
ДокОбъект = Выборка.ПолучитьОбъект();
// Рассчитываем новое время на 23:59:50 того же дня
ДокОбъект.Дата = НачалоДня(ДокОбъект.Дата) + 86390;
Попытка
Если ДокОбъект.Проведен Тогда
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
Иначе
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;
Исключение
Сообщить("Ошибка при обработке документа " + Строка(Выборка.Ссылка) + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Выясним, на какие прикладные механизмы влияет массовое изменение времени документов:
АвтоВремя установлено в значение Первым или Последним, то при последующей интерактивной записи или перепроведении система может повторно изменить время в соответствии со своими настройками.Альтернативный вариант: если требуется разово изменить дату у группы документов в пользовательском режиме без написания кода обработки, можно использовать типовую обработку Групповое изменение реквизитов, указав в поле формулы для реквизита Дата выражение НачалоДня(Объект.Дата) + 86390 с включенным флагом перепроведения.