Разработка и Конфигурация · 11 мин
Как вычислить дату в 1С: полное руководство с примерами
Как вычислить дату в 1С: функции ДобавитьМесяц, ТекущаяДатаСеанса, расчёт разности дат, работа с датами в запросах и типичные ошибки разработчика.
Работа с датами — одна из самых частых задач при разработке и доработке конфигураций 1С. Сроки оплаты, даты отгрузки, расчёт остатков отпусков, периоды отчётов — всё это требует корректных вычислений с типом «Дата». Ошибка в одном дне может привести к неверным начислениям, просроченным документам или сбоям в обменах данными.
Платформа 1С:Предприятие предоставляет встроенный набор функций для арифметики дат, однако у неё есть важные особенности: сложение дат напрямую запрещено, добавление месяца к 31 января даёт неочевидный результат, а работа с датами в запросах отличается от работы в коде. Понимание этих нюансов избавляет от большинства ошибок.
Материал охватывает основные сценарии: получение текущей даты, прибавление и вычитание периодов, расчёт разности между датами, вычисления в запросах и типовые ошибки. Примеры приведены на встроенном языке 1С и применимы как к управляемым, так и к обычным формам.
Получение текущей даты: какой способ выбрать
Первый шаг большинства вычислений — получить точку отсчёта. В 1С есть несколько способов узнать текущую дату, и они не взаимозаменяемы.
Функция ТекущаяДатаСеанса() возвращает дату и время компьютера, на котором выполняется код, с учётом часового пояса сеанса. Именно её рекомендуется использовать в серверном коде и бизнес-логике: она даёт согласованное значение для всех пользователей независимо от настроек их рабочих станций.
Функция ТекущаяДата() на клиенте возвращает время компьютера пользователя, что может расходиться с серверным временем. В тонком клиенте она доступна, но полагаться на неё в расчётах, влияющих на учётные данные, небезопасно: пользователь с неверно установленными часами получит искажённый результат.
Если нужна только дата без времени, обрежьте время функцией НачалоДня():
ТекущаяДата = ТекущаяДатаСеанса();
ДатаБезВремени = НачалоДня(ТекущаяДата);
Прибавление и вычитание дней, часов и секунд
В 1С дата хранится с точностью до секунды, и арифметика дат работает именно в секундах. Чтобы прибавить сутки, добавьте 86400 секунд (60 × 60 × 24). Аналогично час — 3600 секунд, неделя — 604800 секунд.
Завтра = ТекущаяДатаСеанса() + 86400;
НеделюНазад = ТекущаяДатаСеанса() - 7 * 86400;
ЧерезДваЧаса = ТекущаяДатаСеанса() + 2 * 3600;
Для читаемости кода часто заводят переменную СекундВДне = 86400 или используют конструкцию 60*60*24. Это снижает риск опечатки в длинном числе.
Важное ограничение: складывать две даты между собой нельзя — платформа выдаст ошибку. Разрешены только операции «дата плюс число» и «дата минус дата» (результат — число секунд).
Добавление месяцев и лет: функция ДобавитьМесяц
Месяцы имеют разную длину, поэтому прибавлять их через секунды нельзя. Для этого существует функция ДобавитьМесяц(Дата, КоличествоМесяцев). Чтобы прибавить год — передайте 12 месяцев, квартал — 3.
ЧерезМесяц = ДобавитьМесяц(ТекущаяДатаСеанса(), 1);
ЧерезГод = ДобавитьМесяц(ТекущаяДатаСеанса(), 12);
МесяцНазад = ДобавитьМесяц(ТекущаяДатаСеанса(), -1);
Ключевая особенность: если исходный день не существует в целевом месяце, результатом будет последний день этого месяца. Например, ДобавитьМесяц('20260131', 1) вернёт 29 февраля (в високосном году), а не 2–3 марта. При расчёте сроков оплаты «через месяц от конца месяца» это может изменить логику договора — проверяйте требования предметной области.
Вычисление разности между двумя датами
Вычитание дат возвращает разность в секундах. Чтобы получить количество дней, разделите результат на 86400. Для целого числа дней используйте функцию Цел() или округление в зависимости от бизнес-правила.
РазностьСекунд = ДатаОкончания - ДатаНачала;
КоличествоДней = Цел(РазностьСекунд / 86400);
Обратите внимание: если даты содержат время, простое деление может дать «на день меньше», чем ожидает пользователь. Например, разница между 10 марта 09:00 и 12 марта 18:00 — это 2,6 суток, и Цел() даст 2, хотя календарно затронуто 3 дня. Если считаете календарные дни, сначала приведите обе даты к началу дня.
Для расчёта возраста или стажа в полных годах простое деление на 365 непригодно из-за високосных лет. Надёжный подход — сравнить день и месяц рождения с текущими и скорректировать результат.
- 1Приведите обе даты к началу суток: НачалоДня(Дата1) и НачалоДня(Дата2)
- 2Вычтите меньшую дату из большей — получите секунды
- 3Разделите результат на 86400
- 4Проверьте на контрольном примере: разность между 1 и 2 марта должна быть 1
- 5Если нужны рабочие дни — используйте данные производственного календаря, а не простую арифметику
Определение начала и конца периода
Для отборов в запросах, формирования отчётов и проверок попадания даты в период платформа предоставляет семейство функций границ периодов:
НачалоДня(Дата),КонецДня(Дата)— границы суток;НачалоНедели(Дата),КонецНедели(Дата)— неделя начинается с понедельника;НачалоМесяца(Дата),КонецМесяца(Дата);НачалоКвартала(Дата),КонецКвартала(Дата);НачалоГода(Дата),КонецГода(Дата);НачалоЧаса(Дата),КонецЧаса(Дата),НачалоМинуты(Дата),КонецМинуты(Дата).
Конец периода возвращает последнюю секунду: например, КонецДня('20260315') даст 15.03.2026 23:59:59. Это удобно для условий «меньше или равно», но будьте внимательны при сравнении с датами, где время обрезано до дня — документ с 23:59:59 формально не равен дате 15.03.2026 00:00:00.
Типичный приём для отбора за день:
НачалоПериода = НачалоДня(ОтчетнаяДата);
КонецПериода = КонецДня(ОтчетнаяДата);
Вычисление дат в запросах
В языке запросов 1С арифметика секунд недоступна — вместо неё используются специальные функции. Основные из них:
ДОБАВИТЬКДАТЕ(Дата, ТИП, Количество)— прибавляет период, где ТИП принимает значения СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД;РАЗНОСТЬДАТ(Дата1, Дата2, ТИП)— возвращает разность в указанных единицах;НАЧАЛОПЕРИОДА(Дата, ТИП)иКОНЕЦПЕРИОДА(Дата, ТИП)— границы периода;ДАТАВРЕМЯ(2026, 3, 15)— литерал даты, при необходимости с часами, минутами и секундами.
ВЫБРАТЬ
Заказы.Ссылка КАК Заказ,
ДОБАВИТЬКДАТЕ(Заказы.ДатаОтгрузки, ДЕНЬ, 14) КАК СрокОплаты,
РАЗНОСТЬДАТ(Заказы.Дата, Заказы.ДатаОтгрузки, ДЕНЬ) КАК ДнейНаСборку
ИЗ
Документ.ЗаказПокупателя КАК Заказы
РАЗНОСТЬДАТ считает целые единицы: разность между 10:00 и 18:00 одного дня в типе ДЕНЬ даст 0, а в типе ЧАС — 8. Выбирайте единицу измерения, соответствующую бизнес-правилу, и помните, что дробная часть отбрасывается.
Код или запрос: где считать даты
Подходит для сложной логики, циклов, работы с производственным календарём. Полный набор функций, но требует выборки данных в контекст.
Оптимален для вычислений над большими выборками — расчёт выполняется на уровне СУБД без перебора строк. Ограничен набором функций ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ.
Удобен для отчётов: вычисляемые поля с функциями дат прямо в схеме компоновки, без изменения запроса.
Проверка и сравнение дат
Даты сравниваются обычными операторами <, >, =. Однако есть два подводных камня. Первый — пустая дата: значение '00010101' (1 января года 1) меньше любой реальной даты, и условие «дата заполнена» проверяют через ЗначениеЗаполнено(Дата) или сравнение с пустой датой.
Второй — время в составе даты. Две даты одного календарного дня с разным временем не равны. Перед сравнением «тот ли это день» приводите обе к началу дня:
Если НачалоДня(Дата1) = НачалоДня(Дата2) Тогда
// один и тот же календарный день
КонецЕсли;
Для проверки попадания в интервал используйте двойное условие, включая границы осознанно — от этого зависит, попадёт ли документ ровно на границе периода в выборку.
Как проверить результат
Дата сдвинулась ровно на один календарный день, время сохранилось
Смещение на 2 дня или потеря времени
Результат — последний день следующего месяца
Ожидалось 1-е число через месяц, логика сроков нарушена
Целое число, совпадает с подсчётом по календарю
Дробное значение или расхождение на день из-за времени
Документы последнего дня периода попали в выборку
Документы за последний день теряются — конец периода задан как начало дня
Часто задаваемые вопросы
Как прибавить к дате только рабочие дни?
Встроенной функции для рабочих дней нет. Используйте регистр сведений с данными производственного календаря (в типовых конфигурациях — «Регламентированный производственный календарь»): в цикле прибавляйте по одному дню и проверяйте, является ли день рабочим, пока не наберёте нужное количество.
Как узнать день недели для даты?
Функция ДеньНедели(Дата) возвращает число от 1 (понедельник) до 7 (воскресенье). Для названия дня используйте Формат(Дата, "ДФ=dddd").
Чем отличается пустая дата от незаполненной?
Пустая дата — это значение '00010101' (1 января года 1, 00:00:00). Для реквизитов составного типа значение может быть Неопределено. Проверка ЗначениеЗаполнено() корректно отрабатывает оба случая, поэтому предпочтительнее прямого сравнения с '00010101'.
Как вычислить возраст в полных годах?
Вычислите разность лет функцией РАЗНОСТЬДАТ с типом ГОД или через Год() обеих дат, затем уменьшите результат на 1, если день рождения в текущем году ещё не наступил (месяц и день рождения больше текущих). Деление на 365 использовать нельзя из-за високосных лет.
Почему ДОБАВИТЬКДАТЕ в запросе выдаёт ошибку?
Чаще всего неверно указан второй параметр — тип периода пишется без кавычек и только из фиксированного списка: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД. Также проверьте, что первый параметр действительно имеет тип Дата, а не строка или число.
Как получить дату без времени в запросе?
Используйте НАЧАЛОПЕРИОДА(ПолеДаты, ДЕНЬ) — это обрежет время до 00:00:00. Для группировки по дням применяют ту же функцию в секции СГРУППИРОВАТЬ ПО или периодичность итогов виртуальных таблиц.
Что важно запомнить
Арифметика дат в коде 1С работает в секундах: сутки — 86400. Месяцы и годы прибавляйте только через ДобавитьМесяц, в запросах — через ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ. Перед сравнением дат обрезайте время через НачалоДня, а текущую дату в учётной логике берите из ТекущаяДатаСеанса.