При работе со временем и датами в платформе 1С:Предприятие у начинающих разработчиков нередко возникает вопрос: почему конец дня определяется как 23:59:59, и означает ли это, что в сутках платформы содержится 86 399 секунд вместо положенных 86 400? Разберем математическую и программную модель временной оси 1С, выясним логику отсчета секунд, а также рассмотрим механизмы корректного позиционирования событий и получения итогов на границах периодов.
В платформе 1С:Предприятие примитивный тип Дата хранит значение с точностью до одной секунды в формате ГГГГММДДччммсс (без сохранения долей секунд). Каждая сохраненная дата является не протяженным отрезком, а дискретной точкой на временной оси, обозначающей начало соответствующей секунды.
Проанализируем распределение секунд в пределах одних суток:
00:00:00 (охватывает интервал от 00:00:00.000 до 00:00:00.999...).00:00:09.00:59:59.23:59:59 (охватывает интервал от 23:59:59.000 до 23:59:59.999...).Таким образом, утверждение о том, что в сутках 1С не хватает одной секунды — ошибочно. Отсчет времени начинается с нулевой координаты (00:00:00), поэтому последняя, 86 400-я секунда суток имеет индекс со смещением в 86 399 секунд от начала дня и отображается как 23:59:59.
Рассмотрим, почему при вычитании начала дня из конца дня получается число 86 399, а не 86 400:
Конец = КонецДня(ТекущаяДата()); // 23:59:59
Начало = НачалоДня(ТекущаяДата()); // 00:00:00
Разница = Конец - Начало; // 86 399 секунд
Операция вычитания дат возвращает расстояние между двумя точками на оси времени. Расстояние между началом 1-й секунды (00:00:00) и началом 86 400-й секунды (23:59:59) действительно равно ровно 86 399 секундам. Если же мы прибавим к началу дня полную длительность суток (86 400 секунд), то получим точку 00:00:00 уже следующих календарных суток:
СледующиеСутки = НачалоДня(ТекущаяДата()) + 86400; // 00:00:00 следующего дня
Поскольку в одну и ту же секунду в системе может проводиться множество документов, точности типа Дата недостаточно для однозначного выстраивания хронологической последовательности движений. Для решения этой проблемы в 1С применяется специальный объект — МоментВремени.
Он состоит из двух ключевых компонентов:
При проведении документов в оперативном режиме платформа гарантирует, что каждый новый документ получит момент времени, находящийся на оси строго позже всех ранее проведенных документов.
При получении срезов регистров (например, остатков номенклатуры или среза последних курсов валют) критически важно понимать, как платформа обрабатывает граничные условия. Если в виртуальную таблицу передать обычную дату, например, КонецДня(ВыбраннаяДата), платформа по умолчанию применит условие строгого неравенства и не включит движения, сделанные ровно в 23:59:59.
Чтобы гарантированно включить в выборку последнюю секунду периода, необходимо использовать объект Граница с видом границы ВидГраницы.Включая.
Посмотрим на практический пример передачи параметра периода в запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОстаткиНоменклатурыОстатки.Номенклатура,
| ОстаткиНоменклатурыОстатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры.Остатки(&Период, ) КАК ОстаткиНоменклатурыОстатки";
// Формируем границу с включением последней секунды дня
ПериодГраница = Новый Граница(КонецДня(ТекущаяДата()), ВидГраницы.Включая);
Запрос.УстановитьПараметр("Период", ПериодГраница);
Результат = Запрос.Выполнить();
Существует также альтернативный вариант получения остатков на конец суток без использования объекта Граница. Для этого в качестве точки расчета передают начало следующих суток со стандартным исключением границы:
ПериодСледующийДень = НачалоДня(КонецДня(ТекущаяДата()) + 1);
Запрос.УстановитьПараметр("Период", ПериодСледующийДень);
В этом случае все записи, проведенные вплоть до 23:59:59 включительно, гарантированно попадут в расчет остатков, так как они хронологически предшествуют точке 00:00:00 следующего дня.