Как в 1С правильно установить время начала периода на 08:00:00 и перенести проведение документов на конец дня?

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

При разработке внешних обработок выгрузки данных, обменов с кассами и пакетного проведения документов разработчики нередко сталкиваются со специфической работой со временем в платформе 1С:Предприятие. Типичные проблемы — необходимость сместить дату назад на фиксированное число суток с установкой нестандартного утреннего времени (например, 08:00:00), а также гарантированно провести документы в конец дня (23:59:59) без их сброса на текущее время. Разберем по шагам, как решить эти задачи правильно, избегая логических ошибок и перезаписи реквизитов платформенными механизмами.

Задача 1: Установка периода отчета за предыдущие сутки с 08:00:00

Рассмотрим распространенный сценарий: требуется сформировать период для снятия отчетов с кассовых аппаратов. Конечная дата должна указывать на конец текущего дня (23:59:59), а начальная дата — на предыдущий день строго в 08:00:00.

В платформе 1С дата хранится с точностью до секунды, а арифметические операции сложения и вычитания с датой производятся в секундах. Один день содержит 86400 секунд (24 * 60 * 60), а 8 часов — 28800 секунд (8 * 60 * 60).

Если разработчик просто вычитает часы из текущей даты без обнуления секунд или неправильно комбинирует методы, время может сброситься в полночь (00:00:00) или остаться на текущих сутках. Проанализируем корректное решение с использованием математики секунд:


// Сначала сдвигаем текущую дату на 1 день назад (86400 сек),
// затем обрезаем время до 00:00:00 через НачалоДня
// и прибавляем ровно 8 часов (8 * 60 * 60 сек)
ДатаНач = НачалоДня(ТекущаяДата() - 86400) + 8 * 60 * 60;
ДатаКон = КонецДня(ТекущаяДата());

Если необходимо отнимать произвольное количество дней, используем универсальную формулу с множителем:


КолВоДней = 1;
ДатаНач = НачалоДня(ТекущаяДата() - 86400 * КолВоДней) + 8 * 60 * 60;
ДатаКон = КонецДня(ТекущаяДата());

Выясним еще один надежный способ, который исключает ошибки при ручном подсчете секунд — использование конструктора объекта Дата. Разберем этот вариант:


// Получаем расчетную дату за минусом нужного количества дней
ТекДата = НачалоДня(ТекущаяДата() - 86400);

// Собираем точную дату через конструктор: Год, Месяц, День, Час, Минута, Секунда
ДатаНач = Дата(Год(ТекДата), Месяц(ТекДата), День(ТекДата), 8, 0, 0);
ДатаКон = КонецДня(ТекущаяДата());

Обратите внимание: если кассы или рабочие места находятся в разных часовых поясах, вместо функции ТекущаяДата(), возвращающей время сервера, рекомендуется применять ТекущаяДатаСеанса().

Задача 2: Установка времени проведения документов на 23:59:59

Вторая проблема заключается в том, что при пакетном проведении документов (например, кассовых отчетов) время проведения может самопроизвольно устанавливаться в текущее системное время вместо конца дня 23:59:59, нарушая последовательность партионного учета.

Разберем типичную ошибку в обработчике проведения:


Для Каждого СтрокаДок Из ТаблицаДокументов Цикл
    Если СтрокаДок.Пометка Тогда
        ДокументОбъект = СтрокаДок.Документ.ПолучитьОбъект();
        Если ДокументОбъект <> Неопределено И НЕ СтрокаДок.ПометкаУдаления Тогда
            Попытка
                // Ошибка: при вызове без параметров платформа может переопределить время
                ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
                СтрокаДок.Пометка = Ложь;
            Исключение
            КонецПопытки;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Посмотрим на причины, почему время документа сбрасывается или не встает в 23:59:59:

  1. Режим авто-времени: Метод Записать() без явного указания режима авто-времени применяет свойства метаданных документа (по умолчанию — текущее время или время последним в дне). Чтобы принудительно зафиксировать назначенное время, необходимо явно передавать РежимАвтоВремя.НеИспользовать.
  2. Оперативность проведения: Если документ проводится текущим днем в оперативном режиме, платформа принудительно назначает ему текущую системную секунду. Для фиксации времени на границе суток требуется неоперативное проведение.
  3. Изменение даты проведенного документа: Если документ уже был проведен ранее другим временем, перед изменением даты его необходимо сначала расформировать (снять с проведения), изменить реквизит Дата, а затем провести повторно.

Проанализируем правильный алгоритм пакетной установки времени и проведения:


Для Каждого СтрокаДок Из ТаблицаДокументов Цикл
    Если СтрокаДок.Пометка Тогда
        ДокументОбъект = СтрокаДок.Документ.ПолучитьОбъект();
        Если ДокументОбъект <> Неопределено И НЕ СтрокаДок.ПометкаУдаления Тогда
            Попытка
                // 1. Устанавливаем время на конец дня
                ДокументОбъект.Дата = КонецДня(ДокументОбъект.Дата);
                
                // 2. Если документ проведен, отменяем проведение перед сменой времени
                Если ДокументОбъект.Проведен Тогда
                    ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
                КонецЕсли;
                
                // 3. Проводим документ неоперативно без авто-времени
                ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимАвтоВремя.НеИспользовать, РежимПроведенияДокумента.Неоперативный);
                
                СтрокаДок.Пометка = Ложь;
            Исключение
                Сообщить("Ошибка проведения документа: " + ОписаниеОшибки());
            КонецПопытки;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Подводные камни при расстановке документов внутри дня

При автоматическом заполнении нескольких документов на один день часто используют смещение + 1 секунда от предыдущего документа. Рассмотрим критический риск: если предыдущий документ уже имел время 23:59:59, операция Таб[0].Дата + 1 переместит новый документ на 00:00:00 следующих суток. Это приведет к попаданию документа в чужой учетный период.

Для предотвращения перехода через полночь применяйте проверку границ дня:


НоваяДата = Таб[0].Дата + 1;
Если КонецДня(НоваяДата) <> КонецДня(ДатаДокумента) Тогда
    // Если вышли за границы текущего дня, удерживаем время на 23:59:59
    ДокОкс.Дата = КонецДня(ДатаДокумента);
Иначе
    ДокОкс.Дата = НоваяДата;
КонецЕсли;

Соблюдение правил явного отключения авто-времени и контроль переполнения суток обеспечивают корректное формирование кассовых документов и целостность партионного учета.

← На главную