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

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

Как в 1С работать с датой: практическое руководство

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

Дата — один из самых часто используемых типов данных в 1С: ей заполнены документы, регистры, отчёты и отборы. При этом ошибки в работе с датами встречаются постоянно: сбивается формат вывода, дата сравнивается как строка, запрос возвращает пустой результат из-за неверно заданного периода.

Встроенный язык 1С предоставляет отдельный тип «Дата», который хранит дату и время с точностью до секунды, а также набор функций для получения, преобразования и форматирования дат. Важно понимать разницу между датой как значением и её строковым представлением — большинство проблем возникает именно на этом стыке.

Материал охватывает работу с датами в трёх контекстах: во встроенном языке (модули конфигурации), в языке запросов и в пользовательском интерфейсе. Подходы подходят для типовых конфигураций на платформе 8.3, но общие принципы применимы и к более ранним версиям.

Тип «Дата» и способы его создания

Тип «Дата» в 1С объединяет календарную дату и время. Пустое значение даты — это 01.01.0001 00:00:00, и его часто используют как признак «дата не заполнена». Проверка на пустую дату выполняется сравнением с литералом '00010101' или через функцию ЗначениеЗаполнено().

Создать дату можно несколькими способами. Литерал даты записывается в одинарных кавычках в формате ГГГГММДД, например '20260115' или с временем '20260115143000'. Функция Дата() позволяет собрать значение из чисел: Дата(2026, 1, 15, 14, 30, 0) или преобразовать строку.

bsl
// Литерал даты
ДатаДокумента = '20260315';

// Из составляющих
ДатаСобранная = Дата(2026, 3, 15, 10, 30, 0);

// Из строки
ДатаИзСтроки = Дата("20260315103000");

// Проверка на пустую дату
Если Не ЗначениеЗаполнено(ДатаДокумента) Тогда
	Сообщить("Дата не заполнена");
КонецЕсли;

Частая ошибка — сравнение даты со строкой вида «15.03.2026». Такое сравнение работает непредсказуемо, потому что строка автоматически приводится к дате по правилам, зависящим от региональных настроек. Всегда приводите обе стороны сравнения к типу «Дата» явно.

Получение текущей даты и её составляющих

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

Извлечь части даты помогают функции Год(), Месяц(), День(), Час(), Минута(), Секунда() и ДеньНедели(). Для получения начала или конца периода есть готовые функции: НачалоДня(), КонецДня(), НачалоМесяца(), КонецМесяца(), НачалоКвартала(), КонецКвартала(), НачалоГода(), КонецГода(), НачалоНедели(), КонецНедели().

bsl
ТекДата = ТекущаяДатаСеанса();

НачалоТекущегоМесяца = НачалоМесяца(ТекДата);
КонецПрошлогоМесяца = КонецМесяца(ДобавитьМесяц(ТекДата, -1));

НомерГода = Год(ТекДата);
НомерДняНедели = ДеньНедели(ТекДата); // 1 — понедельник, 7 — воскресенье

Функции НачалоДня() и КонецДня() особенно важны при построении отборов по периоду: КонецДня() возвращает 23:59:59, и если вместо неё использовать просто дату без времени (00:00:00), документы, проведённые в течение последнего дня периода, выпадут из выборки.

Типичные ошибки
01
Отбор по периоду с конечной датой 00:00:00 — документы последнего дня не попадают в выборку. Используйте КонецДня() или границу периода.
02
Использование ТекущаяДата() на клиенте при записи документов — время пользователя может отличаться от серверного, что ломает последовательность проведения.
03
Сравнение даты со строкой без явного преобразования — результат зависит от региональных настроек.

Форматирование и вывод даты

Для представления даты пользователю применяется функция Формат() с форматной строкой. Основные шаблоны: ДФ — для даты, ДЛФ — для локализованных форматов. Например, Формат(ДатаДокумента, "ДЛФ=D") выведет длинный формат даты вида «15 марта 2026 г.», а Формат(ДатаДокумента, "ДФ=dd.MM.yyyy") — «15.03.2026».

Полезные параметры форматной строки: ДФ="dd.MM.yyyy HH:mm:ss" — дата со временем, ДФ="MMMM" — название месяца, ДФ="dddd" — день недели. Пустая дата при форматировании по умолчанию превращается в «01.01.0001», чтобы этого избежать, добавьте параметр ДП (дата пустая): Формат(Дата, "ДЛФ=D; ДП='не указана'").

bsl
Формат(ДатаДокумента, "ДЛФ=D");              // 15 марта 2026 г.
Формат(ДатаДокумента, "ДФ=dd.MM.yyyy");       // 15.03.2026
Формат(ДатаДокумента, "ДФ='dd.MM.yyyy HH:mm:ss'"); // 15.03.2026 10:30:00
Формат(ПустаяДата, "ДЛФ=D; ДП='—'");           // —

При выводе дат в печатные формы и отчёты предпочитайте локализованные форматы (ДЛФ) — они автоматически учитывают языковые настройки пользователя. Жёстко зашитый формат «dd.MM.yyyy» уместен в технических строках: именах файлов, обменах, номерах документов.

Арифметика дат: добавление и разница периодов

Простейший способ сдвинуть дату — прибавить или вычесть число секунд: Дата + 86400 сдвинет её на сутки. Такой способ подходит для коротких интервалов, но для месяцев и лет он ненадёжен, потому что месяцы имеют разную длину.

Для сдвига на месяцы используйте функцию ДобавитьМесяц(Дата, КоличествоМесяцев). Она корректно обрабатывает переход через год и короткие месяцы: ДобавитьМесяц('20260131', 1) вернёт 29.02.2026, а не несуществующую дату.

Разность двух дат в секундах получается вычитанием: Разность = Дата2 - Дата1. Чтобы получить разницу в днях, разделите на 86400. Для календарной разницы в месяцах и годах готовой функции нет — её считают через функции запроса РАЗНОСТЬДАТ или собственные алгоритмы с учётом границ месяцев.

bsl
// Сдвиг на 30 дней
ДатаЧерезМесяц = ТекущаяДатаСеанса() + 30 * 86400;

// Корректный сдвиг на 3 месяца
ДатаЧерезКвартал = ДобавитьМесяц(ТекущаяДатаСеанса(), 3);

// Разница в днях
ДнейПросрочено = (ТекущаяДатаСеанса() - ДатаОплаты) / 86400;

Даты в запросах

В языке запросов даты задаются литералом ДАТАВРЕМЯ(2026, 3, 15) или ДАТАВРЕМЯ(2026, 3, 15, 10, 30, 0), либо передаются параметром. Параметры предпочтительнее: текст запроса не нужно пересобирать, и исключены ошибки форматирования.

Для работы с периодами в запросе доступны функции НАЧАЛОПЕРИОДА(Дата, ДЕНЬ|МЕСЯЦ|КВАРТАЛ|ГОД) и КОНЕЦПЕРИОДА(...), а также ДОБАВИТЬКДАТЕ(Дата, МЕСЯЦ, 3). Разницу между датами считает РАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ). Для отбора по регистрам накопления и сведений используйте виртуальные таблицы с параметрами периода — это эффективнее, чем отбор условием ГДЕ по полной таблице.

bsl
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Продажи.Номенклатура,
|	СУММА(Продажи.СуммаОборот) КАК Сумма
|ИЗ
|	РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
|СГРУППИРОВАТЬ ПО
|	Продажи.Номенклатура";
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(Период));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(Период));

При отборе документов по периоду помните о неоднозначности границы: условие Дата МЕЖДУ &Начало И &Конец с конечной датой 00:00:00 пропустит документы последнего дня. Передавайте КонецДня(Период) либо используйте объект Граница с видом «Включая».

Даты в интерфейсе и отчётах

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

В СКД для группировок по времени используйте поля-периоды: День, Неделя, Месяц, Квартал, которые платформа добавляет автоматически для полей типа «Дата». В пользовательских настройках отчёта период лучше задавать через стандартные варианты («Этот месяц», «Прошлый квартал») — они пересчитываются при каждом формировании.

Проверка результата и диагностика проблем

После написания кода или запроса с датами проверьте граничные случаи: пустую дату, переход через месяц и год, високосный февраль, документы, проведённые в 23:59 последнего дня периода. Быстрее всего это сделать в консоли запросов или через «Вычислить выражение» в отладчике.

Признаки типичных проблем: отчёт не видит документы последнего дня (неверная конечная граница), в выгрузке даты сдвинуты на сутки (часовые пояса), строковое сравнение дат даёт неверный порядок сортировки (даты хранятся как строки в формате ДД.ММ.ГГГГ вместо типа «Дата»).

Контрольные точки

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

Границы периода в запросе
Норма

Конечная дата содержит 23:59:59 или задана через КонецДня()

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

Конечная дата с временем 00:00:00 — выпадают документы последнего дня

Хранение даты в реквизите
Норма

Реквизит имеет тип Дата, сортировка и сравнение корректны

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

Дата хранится строкой — сортировка идёт по алфавиту, а не по календарю

Текущая дата в коде
Норма

Используется ТекущаяДатаСеанса()

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

Используется клиентская ТекущаяДата() при записи данных

Итог

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

Дата в 1С — отдельный тип данных: создавайте её литералами и функцией Дата(), получайте текущую через ТекущаяДатаСеанса(), сдвигайте через ДобавитьМесяц(), выводите через Формат(), а в запросах передавайте периоды параметрами с правильными границами. Большинство ошибок связано со строковым представлением дат и неверной конечной границей периода.

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

Как проверить, что дата пустая?

Сравните значение с литералом '00010101' или используйте функцию ЗначениеЗаполнено(): для пустой даты она вернёт Ложь. В запросах условие выглядит как ГДЕ Дата = ДАТАВРЕМЯ(1,1,1).

Как преобразовать строку «15.03.2026» в дату?

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

Почему отчёт не видит документы за последний день периода?

Конечная дата периода задана с временем 00:00:00, то есть на начало суток. Документы, проведённые днём, в интервал не попадают. Передайте в параметр КонецДня(Период) или используйте СтандартныйПериод, который хранит корректную границу 23:59:59.

Как получить разницу между датами в месяцах?

В запросе используйте РАЗНОСТЬДАТ(Дата1, Дата2, МЕСЯЦ). В коде на встроенном языке готовой функции нет: считайте разницу лет и месяцев через Год() и Месяц() с поправкой на день месяца, либо выполните небольшой запрос с РАЗНОСТЬДАТ.

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

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

Как вывести дату в печатной форме без времени?

Примените Формат(ДатаДокумента, "ДЛФ=Д") для длинного локализованного формата («15 марта 2026 г.») или Формат(ДатаДокумента, "ДФ=dd.MM.yyyy") для короткого числового. Время в эти форматы не входит.