Разработка и Конфигурация · 11 мин
Как работать с датами в 1С
Практическое руководство по работе с датами в 1С: тип Дата, функции языка, даты в запросах, форматирование, границы периодов и типичные ошибки разработчиков.
Дата — один из самых часто используемых типов данных в 1С: ей заполнены документы, регистры, отчёты и графики работы. При этом именно с датами связано больше всего тонких ошибок: неверный часовой пояс, «пустая» дата, которая не равна нулю, граница периода, захватывающая лишние секунды. Понимание того, как платформа хранит и обрабатывает даты, избавляет от целого класса дефектов в учёте.
В 1С тип «Дата» всегда содержит и календарную часть, и время с точностью до секунды. Отдельного типа «только дата без времени» в языке нет — когда вы видите дату без времени, время просто равно 00:00:00. Это фундаментальное свойство определяет поведение сравнений, запросов и функций.
Ниже разобраны практические приёмы: создание и форматирование дат, арифметика, работа в запросах, границы периодов и типичные ошибки. Примеры ориентированы на встроенный язык 1С:Предприятия 8.3 и подходят как для управляемых, так и для обычных форм.
Тип «Дата» и его особенности
Внутренне дата в 1С хранится как значение, включающее год, месяц, день, часы, минуты и секунды. Допустимый диапазон — с 01.01.0001 до 31.12.3999. Попытка выйти за эти границы при арифметических операциях приводит к ошибке, поэтому при расчётах с большими смещениями стоит добавлять проверки.
Пустая дата — это 01.01.0001 00:00:00, и именно так проверяют, заполнено ли значение: сравнением с Дата(1,1,1) или функцией ЗначениеЗаполнено(). Важно: пустая дата не равна NULL в запросах. Если поле в запросе может быть NULL (например, из левого соединения), проверять его нужно через ЕСТЬ NULL, а не сравнением с пустой датой.
Создание и получение дат
Конкретную дату создают функцией Дата(). Она принимает либо числовые параметры — год, месяц, день и опционально часы, минуты, секунды, либо строку в формате «ГГГГММДДччммсс». Например: Дата(2026, 3, 15, 10, 30, 0) или Дата("20260315"). Строковый вариант удобен при разборе данных из файлов обмена.
Текущее время получают через ТекущаяДатаСеанса() — это рекомендуемый способ, потому что он учитывает часовой пояс сеанса. Устаревшая ТекущаяДата() берёт время клиентского компьютера, и при разнице часовых поясов между пользователями документы могут «разъезжаться» по датам. В серверном коде всегда используйте дату сеанса.
Из даты извлекают составляющие функциями Год(), Месяц(), День(), Час(), Минута(), Секунда(), а также ДеньНедели(), ДеньГода(), НеделяГода(). Они возвращают числа и удобны для условий вида «только рабочие дни» или «первое число месяца».
НачалоДня = НачалоДня(ТекущаяДатаСеанса());
КонецДня = КонецДня(ТекущаяДатаСеанса()); // 23:59:59
Пустая = Дата(1,1,1);
Если Не ЗначениеЗаполнено(Док.ДатаОплаты) Тогда
Сообщить("Дата оплаты не указана");
КонецЕсли;Форматирование и вывод дат пользователю
Для вывода даты в сообщениях, печатных формах и надписях применяют функцию Формат() со строкой формата. Например, Формат(ДатаДокумента, "ДЛФ=D") выдаёт длинную дату вида «15 марта 2026 г.», а Формат(ДатаДокумента, "ДФ=dd.MM.yyyy") — короткую «15.03.2026». Параметр ДЛФ зависит от региональных настроек, ДФ задаёт шаблон явно.
Для времени используют параметры ДЛФ=T и ДЛФ=DT (дата со временем). При выгрузке в файлы и веб-сервисы дату обычно приводят к формату ISO 8601 через ЗаписатьДатуJSON() или форматную строку "ДФ=yyyy-MM-ddTHH:mm:ss" — так значение однозначно прочитается на принимающей стороне.
Частая ошибка — склеивать дату со строкой напрямую: "Документ от " + ДатаДокумента. Результат зависит от региональных настроек сеанса и может выглядеть иначе на сервере и у пользователя. Всегда оборачивайте дату в Формат() с явным шаблоном.
Арифметика дат и смещение периодов
Сложение и вычитание дат в 1С выполняется в секундах: ДатаДокумента + 86400 сдвинет значение ровно на сутки. Разность двух дат также даёт число секунд, которое затем делят на 60, 3600 или 86400 для получения минут, часов и дней. Помните, что при делении могут остаться дробные остатки — используйте Цел() там, где нужны полные сутки.
Для смещения на месяцы и годы простая арифметика не подходит из-за разной длины месяцев. Используйте ДобавитьМесяц(Дата, КоличествоМесяцев): функция корректно обрабатывает переход через год и короткие месяцы. Например, ДобавитьМесяц(Дата(2026,1,31), 1) вернёт 29.02.2026, а не несуществующее 31 февраля.
Для выравнивания даты на границу периода есть семейство функций: НачалоДня(), КонецДня(), НачалоНедели(), НачалоМесяца(), НачалоКвартала(), НачалоГода() и соответствующие «концы». КонецДня() возвращает 23:59:59 — это важно для отборов периодов, о чём ниже.
- 1Возьмите текущую дату сеанса: ТекущаяДатаСеанса()
- 2Сместите на минус один месяц: ДобавитьМесяц(Дата, -1)
- 3Выровняйте начало: НачалоМесяца(СмещённаяДата)
- 4Получите конец: КонецМесяца(СмещённаяДата)
- 5Используйте обе границы в отборе запроса или отчёта
Даты в запросах
В языке запросов дату-константу задают функцией ДАТАВРЕМЯ(2026, 3, 15, 0, 0, 0). Передавать даты параметрами предпочтительнее: это безопаснее и позволяет оптимизатору строить эффективный план. Параметр объявляется как &НачалоПериода и заполняется значением типа «Дата» перед выполнением запроса.
Для выравнивания в запросе есть функции НАЧАЛОПЕРИОДА(Дата, ДЕНЬ) и КОНЕЦПЕРИОДА(Дата, МЕСЯЦ) с периодичностью от секунды до года. Они особенно удобны при группировках: НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ) сворачивает обороты по месяцам без лишних преобразований в коде.
Отдельная тема — виртуальные таблицы регистров. У таблиц «Остатки», «Обороты», «ОстаткиИОбороты» параметры периода задаются специальным синтаксисом в скобках после имени таблицы, а не в условии ГДЕ. Перепутав место отбора, вы получите корректный, но медленный запрос: платформа сначала выберет всё, а потом отфильтрует.
Границы периодов и отбор «по день включительно»
Классическая проблема: пользователь задаёт период отчёта с 1 по 31 марта, а документы за 31 марта после 00:00:00 в отчёт не попадают. Причина — сравнение Период <= &КонецПериода, где конец периода равен 31.03.2026 00:00:00. Все документы позже полуночи отсекаются.
Решений два. Первое — всегда передавать в качестве конца периода КонецДня(ДатаОкончания), то есть 23:59:59. Второе — использовать объект Граница с видом «Включая»: Новый Граница(ДатаОкончания, ВидГраницы.Включая). Границы особенно важны при работе с регистрами сведений и моментами времени, где секундной точности может не хватать из-за одинакового времени у разных документов.
Для отборов по регистрам, где важна позиция документа, а не просто время, применяйте МоментВремени() документа — он учитывает и дату, и ссылку, что исключает неоднозначность при совпадающих секундах.
Как проверить корректность периода
23:59:59 последнего дня или Граница с видом Включая
00:00:00 последнего дня при сравнении «меньше или равно»
Все документы дня присутствуют
Попадают только документы ровно в 00:00:00
Параметры периода заданы в скобках таблицы
Период фильтруется только в условии ГДЕ
Часовые пояса и дата сеанса
В распределённых системах пользователи могут работать в разных часовых поясах, а сервер — в третьем. Платформа хранит даты без привязки к поясу, поэтому ответственность за корректность лежит на разработчике. Базовое правило: весь серверный код опирается на ТекущаяДатаСеанса(), а пояс сеанса настраивается в свойствах информационной базы или сеанса.
Для преобразований между поясами есть функции МестноеВремя() и УниверсальноеВремя(). Если база обменивается данными с внешними системами, фиксируйте в соглашении об обмене, в каком поясе передаются даты — чаще всего выбирают UTC, чтобы исключить двусмысленность.
Проверки, сравнения и типовые приёмы
Сравнение дат выполняется обычными операторами: больше, меньше, равно. Помните, что сравнивается и время: 15.03.2026 14:00 не равно 15.03.2026 00:00. Если нужно сравнить только календарную часть, предварительно примените НачалоДня() к обоим значениям.
Полезные приёмы, которые встречаются в большинстве конфигураций: проверка попадания даты в период через два сравнения, расчёт возраста или стажа через разность годов с поправкой на месяц и день, определение пересечения двух периодов по правилу «начало первого раньше конца второго и наоборот». Для графиков и производственных календарей сдвиг даты на N рабочих дней делают не арифметикой, а запросом к регистру-календарю — выходные и праздники иначе не учесть.
Как выбрать способ работы с датой
Частые вопросы
Как проверить, что дата не заполнена?
Сравните значение с пустой датой: ДатаПроверки = Дата(1,1,1), либо используйте универсальную функцию ЗначениеЗаполнено(ДатаПроверки) — она вернёт Ложь для пустой даты. В запросе для полей, которые могут быть NULL, проверку делайте через ЕСТЬ NULL, а не сравнением с пустой датой.
Почему документы за последний день не попадают в отчёт?
Потому что конец периода задан как 00:00:00 последнего дня, а документы имеют время позже. Передайте в отчёт КонецДня(ДатаОкончания) — 23:59:59 — или используйте объект Граница с видом «Включая».
Чем отличается ТекущаяДата() от ТекущаяДатаСеанса()?
ТекущаяДата() возвращает время компьютера, на котором выполняется код, а ТекущаяДатаСеанса() — время с учётом часового пояса сеанса, заданного в настройках базы. В клиент-серверном режиме всегда используйте дату сеанса, иначе пользователи из разных поясов создадут документы с несогласованным временем.
Как прибавить к дате один месяц?
Функцией ДобавитьМесяц(Дата, 1). Простое прибавление 30 или 31 дня в секундах даст ошибку на коротких месяцах: ДобавитьМесяц корректно переносит, например, 31 января на последний день февраля.
Как получить только дату без времени?
Отдельного типа «дата без времени» в 1С нет. Примените НачалоДня(Дата) — время станет 00:00:00, и значение можно сравнивать и группировать как календарную дату. При выводе пользователю дополнительно отформатируйте её функцией Формат() без временной части.
Как передать дату в запрос?
Через параметр: в тексте запроса укажите &НачалоПериода, а перед выполнением вызовите Запрос.УстановитьПараметр("НачалоПериода", ЗначениеДаты). Для констант внутри текста запроса используйте ДАТАВРЕМЯ(год, месяц, день, часы, минуты, секунды), но параметры предпочтительнее — они безопаснее и быстрее.
Что важно запомнить
Дата в 1С всегда содержит время до секунды; пустая дата — это 01.01.0001. Создавайте даты через Дата(), форматируйте через Формат(), смещайте через ДобавитьМесяц() и арифметику в секундах. В запросах используйте ДАТАВРЕМЯ, НАЧАЛОПЕРИОДА и параметры, а конец периода задавайте как 23:59:59 или границей «Включая». В серверном коде опирайтесь на ТекущаяДатуСеанса().