К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как в 1С к дате прибавить часы

Как в 1С прибавить часы к дате: сложение с секундами, функция ДобавитьКДате, работа с часовыми поясами. Примеры кода, типичные ошибки и проверка результата.

Дата в 1С хранится с точностью до секунды, поэтому «прибавить часы» всегда означает одно и то же действие: добавить к значению типа Дата нужное количество секунд. Час — это 3600 секунд, и простейший рабочий вариант выглядит так: НоваяДата = СтараяДата + Часы * 3600;. Этот приём работает во всех версиях платформы и не требует никаких дополнительных библиотек.

Второй штатный способ — функция ДобавитьКДате(), которая умеет добавлять не только часы, но и минуты, дни, месяцы и годы с корректной обработкой переходов через границы периодов. Выбор между двумя подходами зависит от задачи: для простого сдвига в пределах суток достаточно сложения, а для универсального механизма сдвигов удобнее специализированная функция.

Ниже разобраны оба способа с примерами кода, показано, как прибавлять часы в запросах, как учитывать часовые пояса и какие ошибки чаще всего приводят к неверному результату.

Как устроен тип Дата в 1С и почему часы складывают через секунды

Тип Дата в платформе 1С содержит календарную дату и время с точностью до секунды. Внутренне это значение, к которому можно прибавлять и вычитать числа — и число всегда интерпретируется как количество секунд. Поэтому выражение Дата + 1 сдвигает дату ровно на одну секунду, а не на один день, как ошибочно ожидают многие начинающие разработчики.

Из этого правила вытекает простая арифметика: одна минута — 60 секунд, один час — 3600 секунд, одни сутки — 86400 секунд. Чтобы прибавить, например, 5 часов к текущей дате, достаточно написать ТекущаяДатаСеанса() + 5 * 3600. При выходе за границу суток платформа сама корректно перенесёт значение на следующий день, месяц или год — отдельно обрабатывать переход не нужно.

Вычитание двух дат тоже возвращает результат в секундах. Это удобно для контроля: если нужно проверить, что сдвиг выполнен правильно, вычтите исходную дату из итоговой и разделите на 3600 — должно получиться исходное число часов.

Способ 1: сложение даты с числом секунд

Самый короткий и универсальный метод — прямое сложение. Он работает в любом контексте: на клиенте, на сервере, в тонком и веб-клиенте, в любой версии платформы 8.x. Пример:

ИсходнаяДата = ТекущаяДатаСеанса();

КоличествоЧасов = 8;

НоваяДата = ИсходнаяДата + КоличествоЧасов * 3600;

Для читаемости кода константу 3600 часто выносят в именованную переменную или функцию. Если сдвиг в часах используется в нескольких местах модуля, удобно оформить небольшую функцию-обёртку:

Функция ПрибавитьЧасы(Дата, Часы)

Возврат Дата + Часы * 3600;

КонецФункции

Отрицательное значение часов работает симметрично: Дата + (-3) * 3600 отнимет три часа. Это позволяет использовать одну и ту же конструкцию и для сдвига назад, не вводя отдельную операцию вычитания.

Ограничение способа — он сдвигает строго на физические секунды. Если требуется «календарная» логика (например, прибавить месяц с учётом разного числа дней), сложение не подходит — понадобится ДобавитьКДате().

Способ 2: функция ДобавитьКДате()

Встроенная функция ДобавитьКДате(Дата, Тип, Количество) добавляет к дате заданное число единиц указанного типа. Для часов второй параметр принимает значение "Час" (или "Hour" в английском синтаксисе):

НоваяДата = ДобавитьКДате(ИсходнаяДата, "Час", 6);

Функция корректно обрабатывает переходы через границы суток, месяцев и лет. Например, добавление 5 часов к 22:00 даст 03:00 следующего дня без дополнительного кода. Отрицательное количество отнимает часы.

Заодно ДобавитьКДате() поддерживает типы Секунда, Минута, День, Неделя, Месяц, Квартал, Год, поэтому её удобно применять в универсальных механизмах, где единица сдвига задаётся настройкой. Для простого «плюс N часов» оба способа равнозначны по результату; разница лишь в читаемости и универсальности кода.

Сравнение вариантов

Сложение Дата + Часы * 3600

Подходит для простого сдвига на часы или минуты; работает везде; не решает календарные задачи вроде добавления месяцев.

ДобавитьКДате()

Удобна, когда единица сдвига задаётся параметром или нужны месяцы и годы; чуть длиннее запись.

ДОБАВИТЬКДАТЕ в запросе

Единственный вариант, когда сдвиг нужно выполнить на стороне СУБД без обхода выборки в коде.

Как прибавить часы к дате в запросе

В языке запросов 1С сложение даты с числом недоступно, поэтому используется функция ДОБАВИТЬКДАТЕ(Дата, Тип, Количество). Тип указывается ключевым словом без кавычек: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ и так далее.

ВЫБРАТЬ

ДОБАВИТЬКДАТЕ(Заказы.ДатаОтгрузки, ЧАС, 12) КАК Дедлайн

ИЗ

Документ.ЗаказПокупателя КАК Заказы

Такой приём полезен, когда сдвинутая дата нужна прямо в выборке — например, для расчёта крайнего срока, фильтрации по окну времени или соединения таблиц по интервалу. Количество может быть и выражением, в том числе отрицательным.

Учитывайте, что сдвиг выполняется на сервере СУБД, и значения дат в базе хранятся, как правило, в едином часовом поясе сеанса записи. Если в запросе сравниваются даты из разных источников, убедитесь, что все они приведены к одному поясу, иначе сдвиг даст обманчиво «правильный», но фактически неверный результат.

bsl
НоваяДата = ДобавитьКДате(ТекущаяДатаСеанса(), "Час", 4);

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

Функция ТекущаяДата() возвращает время компьютера, на котором выполняется код, поэтому в клиент-серверном режиме результат на клиенте и на сервере может различаться. Для прикладной логики рекомендуется ТекущаяДатаСеанса() — она приводится к часовому поясу сеанса и даёт согласованные значения.

Если нужно получить время в другом часовом поясе — например, московское время при сервере в другом регионе — используются функции работы с датами и поясами: МестноеВремя(), УниверсальноеВремя(), ТекущаяУниверсальнаяДата(). Прибавление часов к универсальному времени безопасно, а вот «ручной» сдвиг локального времени на разницу поясов ломается при переводе часов или смене правил пояса.

Проверка результата и типичные ошибки

Проверить сдвиг проще всего разностью дат: вычтите исходное значение из итогового и разделите на 3600. Если получили исходное количество часов без дробной части — сдвиг выполнен верно. Для визуального контроля выведите обе даты через Формат(Дата, "ДЛФ=DT"), чтобы видеть и день, и время.

Частая ошибка — прибавление часов к дате с «обрезанным» временем. Например, функция НачалоДня(Дата) возвращает 00:00:00, и если разработчик ожидал текущее время, а получил полночь, итоговый сдвиг окажется не тем. Перед сложением всегда проверяйте, какое именно время содержит исходное значение.

Вторая распространённая проблема — пустая дата (01.01.0001 00:00:00) в реквизите. Прибавление часов к пустой дате выполнится без ошибки, но результат будет бессмысленным. Перед расчётом стоит проверять ЗначениеЗаполнено(Дата) и обрабатывать пустое значение отдельно.

Типичные ошибки
01
Прибавление числа часов без умножения на 3600 — дата сдвигается на секунды вместо часов
02
Сложение с датой, содержащей начало дня вместо ожидаемого времени — итог смещён на часы
03
Игнорирование пустой даты в реквизите — получается дата от 01.01.0001, которая ломает отчёты и отборы
04
Смешение ТекущаяДата() на клиенте и на сервере — в разных поясах результаты расходятся
Контрольные точки

Как проверить результат

Разность итоговой и исходной даты, делённая на 3600
Норма

Целое число, равное количеству добавленных часов

Тревожный признак

Дробное значение или ноль — сдвиг выполнен неверно

Время в исходной дате перед расчётом
Норма

Ожидаемое время (например, текущее)

Тревожный признак

00:00:00 там, где должно быть реальное время

Переход через полночь
Норма

Дата корректно перешла на следующие сутки

Тревожный признак

Время изменилось, а день остался прежним

Практические сценарии использования

Типовая задача — расчёт крайнего срока: например, реакция на заявку в течение 4 рабочих часов. Если учёт не завязан на производственный календарь, достаточно ДатаПоступления + 4 * 3600. Если же часы должны быть именно рабочими, простым сложением не обойтись — потребуется график работы и цикл по интервалам.

Другой сценарий — округление и нормализация времени перед сдвигом. Например, чтобы получить «следующий час от начала текущего», комбинируют НачалоЧаса() и сложение: НачалоЧаса(ТекущаяДатаСеанса()) + 3600. Аналогично работают КонецЧаса(), НачалоМинуты() и родственные функции.

При обмене данными со внешними системами часы часто добавляют для приведения времени к формату контрагента. Здесь важно зафиксировать в коде, в каком поясе хранятся даты в базе, и выполнять сдвиг один раз в одном месте — размазанные по модулям поправки «плюс N часов» быстро приводят к двойным сдвигам.

Итог

Что важно запомнить

Часы к дате в 1С прибавляют через секунды: Дата + Часы * 3600, либо функцией ДобавитьКДате(Дата, "Час", N), а в запросах — ДОБАВИТЬКДАТЕ(Дата, ЧАС, N). Перед расчётом проверяйте время в исходной дате, пустые значения и часовой пояс; правильность сдвига контролируйте разностью дат.

Частые вопросы

Как отнять часы от даты в 1С?

Используйте отрицательное количество: Дата - Часы * 3600 или ДобавитьКДате(Дата, "Час", -Часы). Оба варианта корректно обрабатывают переход через полночь в обратную сторону.

Почему Дата + 1 не прибавляет день?

Арифметика с датами в 1С работает в секундах, поэтому Дата + 1 добавляет одну секунду. Для суток используйте 86400 секунд или ДобавитьКДате(Дата, "День", 1).

Как прибавить часы к дате в запросе 1С?

Примените функцию языка запросов ДОБАВИТЬКДАТЕ: ДОБАВИТЬКДАТЕ(Поле.Дата, ЧАС, 3). Тип интервала пишется без кавычек, количество может быть отрицательным или вычисляемым выражением.

Чем ТекущаяДата() отличается от ТекущаяДатаСеанса() при расчётах?

ТекущаяДата() возвращает время того компьютера, где выполняется код, а ТекущаяДатаСеанса() — время, приведённое к часовому поясу сеанса. В клиент-серверном режиме для прикладных расчётов надёжнее ТекущаяДатаСеанса(), иначе результаты на клиенте и сервере могут различаться.

Как прибавить только рабочие часы, а не календарные?

Простым сложением это не решается: потребуется график работы (производственный календарь или регистр с интервалами) и цикл, который проходит по рабочим периодам, накапливая нужное количество часов. Готовой встроенной функции для рабочих часов в платформе нет.

Что будет, если прибавить часы к пустой дате?

Ошибки не возникнет: пустая дата (01.01.0001 00:00:00) просто сдвинется на указанное число секунд. Такой результат обычно бессмысленен и может испортить отборы и отчёты, поэтому перед расчётом проверяйте реквизит через ЗначениеЗаполнено().