Дата в запросе 1С: ДАТАВРЕМЯ, сравнение и функции дат

Дата: 21.09.2026 07:06:43
Запросы
Язык запросов
Даты
ДАТАВРЕМЯ
ВЫРАЗИТЬ
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

Дата в запросе 1С задаётся литералом ДАТАВРЕМЯ или параметром, а для работы с ней в языке запросов есть полтора десятка функций — от ГОД() и ДЕНЬНЕДЕЛИ() до НАЧАЛОПЕРИОДА() и РАЗНОСТЬДАТ(). Ниже — шпаргалка по функциям дат, сравнение без учёта времени, группировка по месяцам и дням недели, что на самом деле делает ВЫРАЗИТЬ(... КАК ДАТА) и как быть с датой, которая хранится строкой. Примеры — для платформы 8.3 и любой конфигурации; имена документов и реквизитов условные, подставьте свои.

Где встречается задача

  • отбор документов за день, месяц или произвольный период;
  • группировка продаж по месяцам, неделям, дням недели;
  • поиск незаполненных дат: заказы без даты отгрузки, договоры без срока действия;
  • сравнение дат из двух таблиц «в один день» — например, оплата в день отгрузки;
  • даты, которые пришли строкой: загрузка из Excel, дополнительные реквизиты, данные обмена;
  • проверка пересечения периодов — см. статью о пересечении периодов в запросе.

Дата в запросе 1С: шпаргалка по функциям

ФункцияЧто возвращаетПример
ДАТАВРЕМЯ(Г, М, Д[, Ч, Мин, С])дату-константуДАТАВРЕМЯ(2024, 1, 1)
ГОД(Дата)номер годаГОД(Док.Дата) = 2024
КВАРТАЛ(Дата)квартал, 1–4КВАРТАЛ(Док.Дата) = 4
МЕСЯЦ(Дата)месяц, 1–12МЕСЯЦ(Док.Дата) = 12
ДЕНЬГОДА(Дата)день года, 1–366ДЕНЬГОДА(Док.Дата)
ДЕНЬ(Дата)день месяца, 1–31ДЕНЬ(Док.Дата) = 1
НЕДЕЛЯ(Дата)номер недели в годуНЕДЕЛЯ(Док.Дата)
ДЕНЬНЕДЕЛИ(Дата)1 — понедельник … 7 — воскресеньеДЕНЬНЕДЕЛИ(Док.Дата) В (6, 7)
ЧАС, МИНУТА, СЕКУНДАчасти времениЧАС(Док.Дата) >= 18
НАЧАЛОПЕРИОДА(Дата, Период)первую секунду периодаНАЧАЛОПЕРИОДА(Док.Дата, МЕСЯЦ)
КОНЕЦПЕРИОДА(Дата, Период)последнюю секунду периодаКОНЕЦПЕРИОДА(&Дата, ДЕНЬ)
ДОБАВИТЬКДАТЕ(Дата, Тип, Число)дату, сдвинутую на N единицДОБАВИТЬКДАТЕ(Док.Дата, ДЕНЬ, 10)
РАЗНОСТЬДАТ(Дата1, Дата2, Тип)разницу в заданных единицахРАЗНОСТЬДАТ(Док.Дата, &ТекущаяДата, ДЕНЬ)

Период для НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА пишется словом без кавычек: МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД, ДЕКАДА, ПОЛУГОДИЕ. Неделя начинается с понедельника. Функции частей даты возвращают числа, поэтому сравнивать их нужно с числом: МЕСЯЦ(Док.Дата) = 12, а не со строкой «12».

Складывать и вычитать даты знаками + и - в запросе нельзя: для сдвига есть ДОБАВИТЬКДАТЕ, для разницы — РАЗНОСТЬДАТ. Обе функции подробно разобраны в статье о ДОБАВИТЬКДАТЕ в запросе.

Литерал ДАТАВРЕМЯ и пустая дата

Литерала даты вида '20240101', как во встроенном языке, в запросе нет — только функция ДАТАВРЕМЯ. Её аргументы — числа прямо в тексте запроса: год, месяц, день и при необходимости час, минута, секунда. Поле, параметр или выражение туда не подставить: запрос не пройдёт проверку синтаксиса.

ВЫБРАТЬ
	Заказ.Ссылка КАК Заказ,
	Заказ.Дата КАК Дата
ИЗ
	Документ.ЗаказКлиента КАК Заказ
ГДЕ
	Заказ.Дата >= ДАТАВРЕМЯ(2024, 1, 1)
	И Заказ.Дата < ДАТАВРЕМЯ(2024, 4, 1)
	И Заказ.ДатаОтгрузки = ДАТАВРЕМЯ(1, 1, 1)

Запрос выбирает заказы первого квартала 2024 года, у которых не заполнена дата отгрузки. ДАТАВРЕМЯ(1, 1, 1) — пустая дата, 01.01.0001 00:00:00: так в запросе проверяют незаполненный реквизит типа Дата. Конец квартала задан условием «меньше 1 апреля»: вариант «меньше или равно 31 марта» потеряет документы 31 марта с ненулевым временем.

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

// Код на сервере. Период — реквизит типа СтандартныйПериод.
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(Период.ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(Период.ДатаОкончания));
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
Запрос.УстановитьПараметр("ПустаяДата", Дата(1, 1, 1));

Сравнение дат без учёта времени

Реквизит Дата у документа хранит и время. Если передать в параметр 15.01.2024 и написать Док.Дата = &Дата, найдутся только документы с временем 00:00:00 — на практике почти никакие. День нужно задавать интервалом.

УсловиеКогда использовать
Док.Дата МЕЖДУ &НачалоДня И &КонецДняОсновной вариант: границы считаются в коде функциями НачалоДня() и КонецДня(), индекс по дате работает.
Док.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ)То же, но границы считает запрос — удобно, когда параметр приходит «как есть», например из пользовательских настроек СКД. Функция применяется к параметру, а не к полю, и индексу не мешает.
НАЧАЛОПЕРИОДА(Док.Дата, ДЕНЬ) = &ДатаРезультат верный, но функция считается для каждой строки, и СУБД, как правило, не может использовать индекс по дате. На больших журналах это заметно медленнее.

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

ВЫБРАТЬ
	Реализация.Ссылка КАК Реализация,
	Оплата.Ссылка КАК Оплата
ИЗ
	Документ.РеализацияТоваровУслуг КАК Реализация
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеБезналичныхДенежныхСредств КАК Оплата
		ПО (Оплата.Контрагент = Реализация.Контрагент)
			И (НАЧАЛОПЕРИОДА(Оплата.Дата, ДЕНЬ) = НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ))
ГДЕ
	Реализация.Проведен
	И Оплата.Проведен
	И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
	И Оплата.Дата МЕЖДУ &НачалоПериода И &КонецПериода

Ограничьте периодом обе таблицы. Если границы выровнены по дням (НачалоДня() и КонецДня()), условие на Оплата.Дата результат не меняет, зато СУБД отберёт оплаты по индексу, и функции в условии соединения посчитаются для небольшого набора строк, а не для всех оплат за всё время. Как ещё отбирать документы за период и по реквизитам, описано в статье о запросах к документам.

Группировка по месяцам: НАЧАЛОПЕРИОДА или МЕСЯЦ

Для помесячной разбивки есть два пути с разным результатом. НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) возвращает дату — 01.02.2024, 01.03.2024 — и отличает январь 2024 от января 2025. МЕСЯЦ(Дата) возвращает число от 1 до 12 и сложит январи разных лет в одну строку. Для динамики по месяцам берите первый вариант, для сезонности («все декабри за пять лет») — второй вместе с ГОД().

ВЫБРАТЬ
	НАЧАЛОПЕРИОДА(Реализация.Дата, МЕСЯЦ) КАК НачалоМесяца,
	СУММА(Реализация.СуммаДокумента) КАК Сумма
ИЗ
	Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
	Реализация.Проведен
	И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО
	НАЧАЛОПЕРИОДА(Реализация.Дата, МЕСЯЦ)

УПОРЯДОЧИТЬ ПО
	НачалоМесяца

В СГРУППИРОВАТЬ ПО выражение повторяется целиком, псевдоним там не подойдёт; в УПОРЯДОЧИТЬ ПО псевдоним допустим. Если те же данные уже лежат в регистре накопления, помесячные итоги проще взять из виртуальной таблицы Обороты с периодичностью Месяц: поле Период там уже содержит начало месяца.

День недели в запросе 1С

ДЕНЬНЕДЕЛИ() возвращает число: 1 — понедельник, 7 — воскресенье. Документы, созданные в выходные, отбираются условием ДЕНЬНЕДЕЛИ(Док.Дата) В (6, 7), вечерние — через ЧАС(Док.Дата) >= 18. Название дня в запросе получают конструкцией ВЫБОР. Готовая функция для отчёта «выручка по дням недели» покажет владельцу магазина, в какие дни продажи проседают:

// Выручка по дням недели за период.
// Размещение: серверный общий модуль или модуль менеджера отчёта.
// Имена объектов условные: документ РеализацияТоваровУслуг с реквизитом СуммаДокумента.
Функция ВыручкаПоДнямНедели(Знач НачалоПериода, Знач КонецПериода) Экспорт

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

	// Границы дня считаем в коде: условие по полю Дата остаётся простым
	// и не зависит от того, какое время выбрал пользователь.
	Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
	Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));

	Возврат Запрос.Выполнить().Выгрузить();

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

Разбор ключевых строк

  • Вложенный запрос. Группировка идёт по числу ДЕНЬНЕДЕЛИ(Реализация.Дата), а название дня добавляет внешний запрос. Так не приходится повторять громоздкий ВЫБОР в СГРУППИРОВАТЬ ПО.
  • НачалоДня() и КонецДня(). Даже если пользователь выбрал период с временем, граничные дни войдут целиком: МЕЖДУ включает обе границы, а КонецДня() даёт 23:59:59.
  • Результат. Не больше семи строк; дней без продаж в таблице не будет — для полной недели дополните её в коде.

Из модуля формы функцию вызывают в процедуре с директивой &НаСервере или &НаСервереБезКонтекста. Общий синтаксис разобран в статье о языке запросов 1С.

Выразить как дата в запросе 1С 8.3

ВЫРАЗИТЬ в языке запросов не переводит значение из одного типа в другой: он выделяет нужный тип из поля составного типа или меняет квалификаторы, например длину строки. Типичный случай — дополнительные реквизиты БСП: колонка Значение там составного типа, и дата хранится вперемешку со строками, числами и ссылками. Чтобы сравнить её с датой, нужно явно выделить часть «Дата»:

ВЫБРАТЬ
	ДопРеквизиты.Ссылка КАК Договор,
	ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК ДАТА) КАК ДатаОкончания
ИЗ
	Справочник.ДоговорыКонтрагентов.ДополнительныеРеквизиты КАК ДопРеквизиты
ГДЕ
	ДопРеквизиты.Свойство = &СвойствоДатаОкончания
	И ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК ДАТА) < &ТекущаяДата

Для значения другого типа ВЫРАЗИТЬ вернёт NULL, и строка в результат не попадёт.

Выразить как дату без времени не получится: ВЫРАЗИТЬ время не обрезает. Состав даты (дата, время, дата и время) задаётся квалификатором реквизита в конфигураторе, а не в запросе. Чтобы отбросить время, используйте НАЧАЛОПЕРИОДА(Поле, ДЕНЬ).

Выразить как дату и время отдельно не нужно: ДАТАВРЕМЯ — функция, а не тип, а ВЫРАЗИТЬ(... КАК ДАТА) и так возвращает значение вместе с хранившимся в нём временем.

Почему строку нельзя выразить как дату и как это обойти

Запрос вида ВЫРАЗИТЬ(Т.ДатаСтрокой КАК ДАТА) выполнен не будет: разбирать строку в дату язык запросов не умеет. Функции, превращающей строку в число, в языке запросов тоже нет: СТРОКА() из 8.3.20 работает только в обратную сторону. Собрать дату из кусочков ПОДСТРОКА формально можно, если переводить каждую цифру в число громоздким ВЫБОР, но такой запрос тяжело читать и сопровождать.

Обходных путей три.

  1. Исправить хранение. Добавьте реквизит типа Дата и один раз заполните его обработкой — дальше отборы и сортировка работают без ухищрений.
  2. Преобразовать в коде и передать таблицу в запрос. Строки разбирает встроенный язык, результат уходит в запрос параметром и становится временной таблицей. Так сверяют реестр поставщика из Excel с поступлениями.
  3. Собрать дату из чисел. Если год и месяц хранятся числами, дату можно собрать прямо в запросе через ДОБАВИТЬКДАТЕ от базовой даты.

Второй вариант в коде:

// Серверный общий модуль. ДанныеФайла — таблица значений с колонками
// НомерСтрокой и ДатаСтрокой: строки вида "15.01.2024", например прочитанные из Excel.
Функция НайтиПоступленияПоРеестру(ДанныеФайла) Экспорт

	Реестр = Новый ТаблицаЗначений;
	Реестр.Колонки.Добавить("Номер", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(30)));
	Реестр.Колонки.Добавить("ДатаДокумента",
		Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата)));

	Для Каждого СтрокаФайла Из ДанныеФайла Цикл
		НоваяСтрока = Реестр.Добавить();
		НоваяСтрока.Номер = СокрЛП(СтрокаФайла.НомерСтрокой);
		НоваяСтрока.ДатаДокумента = ДатаИзСтроки(СтрокаФайла.ДатаСтрокой);
	КонецЦикла;

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Реестр.Номер КАК Номер,
	|	Реестр.ДатаДокумента КАК ДатаДокумента
	|ПОМЕСТИТЬ ВТ_Реестр
	|ИЗ
	|	&Реестр КАК Реестр
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВТ_Реестр.Номер КАК Номер,
	|	ВТ_Реестр.ДатаДокумента КАК ДатаДокумента,
	|	Поступление.Ссылка КАК Документ
	|ИЗ
	|	ВТ_Реестр КАК ВТ_Реестр
	|		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг КАК Поступление
	|		ПО (Поступление.НомерВходящегоДокумента = ВТ_Реестр.Номер)
	|			И (НАЧАЛОПЕРИОДА(Поступление.ДатаВходящегоДокумента, ДЕНЬ) = ВТ_Реестр.ДатаДокумента)
	|			И (ВТ_Реестр.ДатаДокумента <> ДАТАВРЕМЯ(1, 1, 1))
	|			И (НЕ Поступление.ПометкаУдаления)";
	Запрос.УстановитьПараметр("Реестр", Реестр);

	Возврат Запрос.Выполнить().Выгрузить();

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

// Разбирает строку "ДД.ММ.ГГГГ". Если строка не похожа на дату, возвращает пустую дату.
Функция ДатаИзСтроки(Знач Текст)

	Части = СтрРазделить(СокрЛП(Текст), ".", Ложь);
	Если Части.Количество() <> 3 Или СтрДлина(Части[2]) <> 4 Тогда
		Возврат Дата(1, 1, 1);
	КонецЕсли;

	Попытка
		Возврат Дата(Число(Части[2]), Число(Части[1]), Число(Части[0]));
	Исключение
		Возврат Дата(1, 1, 1);
	КонецПопытки;

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

Колонки таблицы типизированы явно: без описания типов запрос не поместит таблицу во временную и остановится с ошибкой «Тип не может быть выбран в запросе». СтрРазделить() доступна с 8.3.6. Нераспознанная дата становится пустой, и условие <> ДАТАВРЕМЯ(1, 1, 1) не даёт такой строке ложно совпасть с поступлением без входящей даты: поле Документ у неё будет NULL — покажите такие строки пользователю. Помеченные на удаление поступления в сверку не попадают. Двузначный год («15.01.24») функция намеренно не принимает. Подробнее о передаче таблиц в запрос — в статье о таблице значений в запросе.

Третий вариант — для регистра планов, где год и месяц хранятся числовыми измерениями:

ВЫБРАТЬ
	Планы.Номенклатура КАК Номенклатура,
	ДОБАВИТЬКДАТЕ(
		ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2000, 1, 1), ГОД, Планы.НомерГода - 2000),
		МЕСЯЦ, Планы.НомерМесяца - 1) КАК НачалоМесяца,
	Планы.Количество КАК Количество
ИЗ
	РегистрСведений.ПланыПродажПоМесяцам КАК Планы

Особый случай — строка в формате ГГГГММДД («20240115»). Её можно не преобразовывать: при фиксированной длине сравнение строк совпадает с хронологическим, и условие Т.ДатаСтрокой МЕЖДУ "20240101" И "20240131" отберёт январь. Строки неограниченной длины в запросе сравнивать нельзя, поэтому такой реквизит сначала ограничьте: ВЫРАЗИТЬ(Т.ДатаСтрокой КАК СТРОКА(8)) МЕЖДУ "20240101" И "20240131".

Типичные ошибки

  • Док.Дата <= &Дата, где в параметре дата без времени. Документы последнего дня с временем позже 00:00:00 выпадают. Передавайте КонецДня(Дата).
  • Арифметика над датой. Док.Дата + 1 или &Дата - 86400 запрос не примет. Используйте ДОБАВИТЬКДАТЕ.
  • Параметр или поле внутри ДАТАВРЕМЯ. ДАТАВРЕМЯ(&Год, 1, 1) — синтаксическая ошибка. Соберите дату в коде и передайте параметром.
  • Не установлен параметр даты. Опечатка в имени параметра даёт ошибку «Не задано значение параметра "КонецПериода"». Имя в УстановитьПараметр() должно совпадать с именем после &.
  • Запрос в клиентской процедуре. Новый Запрос на клиенте падает с ошибкой «Тип не определен (Запрос)». Запрос выполняется только на сервере.
  • Остатки «на дату» без движений этой даты. Остатки(&Дата) возвращает остаток на начало указанного момента. Чтобы учесть движения за весь день, передайте Новый Граница(КонецДня(Дата), ВидГраницы.Включая).
  • Пустая дата и NULL. После левого соединения недостающая дата — это NULL, а не ДАТАВРЕМЯ(1, 1, 1). Проверяйте ЕСТЬ NULL или приводите через ЕСТЬNULL(Поле, ДАТАВРЕМЯ(1, 1, 1)).

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

Как получить текущую дату в запросе 1С?

Функции текущей даты в языке запросов нет. Передайте её параметром: Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса()). В вычисляемых полях СКД есть своя функция ТекущаяДата() языка выражений.

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

НАЧАЛОПЕРИОДА(Поле, ДЕНЬ) — время станет 00:00:00. ВЫРАЗИТЬ(Поле КАК ДАТА) для этого не подходит: время он не отбрасывает.

Как вывести дни без продаж?

Запрос возвращает только те даты, которые есть в данных. Пропуски дополняет ключевое слово ПЕРИОДАМИ в секции ИТОГИ, например ИТОГИ СУММА(Сумма) ПО Период ПЕРИОДАМИ(ДЕНЬ, &НачалоПериода, &КонецПериода), но только при обходе Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Период", "ВСЕ"): без третьего параметра "ВСЕ" пустые дни не появятся. В СКД для этого есть настройка дополнения периодов у поля группировки. Или добавьте недостающие строки в коде.

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

С 8.3.20 есть функция СТРОКА(), но вид результата зависит от национальных настроек. Надёжнее выбрать дату как есть и отформатировать при выводе функцией Формат() или в настройках СКД. Остальные строковые функции собраны в статье о строках в запросе.

Работают ли эти функции в СКД?

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

Когда проще заказать

Если отчёт с периодами собирает данные из нескольких регистров, должен считать рабочие дни или сверять даты из чужих файлов, быстрее отдать его программисту — посмотрите услугу отчёты и обработки 1С. Опишите задачу на странице «Разместить задание»: оценка бесплатная, ответ в течение рабочего дня.

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.