Работа с датами в запросах 1С — одна из самых распространённых задач при разработке отчётов, обработок и аналитических выборок. Однако многие программисты сталкиваются с проблемами, когда система неверно интерпретирует введённую дату или игнорирует её формат. Почему так происходит? Дело в том, что 1С:Предприятие использует собственные правила обработки дат, которые отличаются от стандартного SQL.
В этой статье мы разберём все способы явного указания даты в запросах — от базового синтаксиса до продвинутых техник с использованием функций ДАТАВРЕМЯ(), НАЧАЛОПЕРИОДА() и других. Вы узнаете, как избежать типичных ошибок при фильтрации по датам, как правильно задавать интервалы и какие нюансы учитывать при работе с разными версиями платформы. Особое внимание уделим разнице между строковым представлением даты и её внутренним форматом в 1С, которая часто становится причиной сбоев в выборках.
Базовый синтаксис указания даты в запросах 1С
Самый простой способ задать дату в запросе — использовать литерал даты в формате 'ГГГГ-ММ-ДД'. Например:
ВЫБРАТЬ
ДатаДокумента КАК Дата,
СуммаДокумента КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента = ДАТАВРЕМЯ(2026, 05, 15)
Но что если вам нужно указать дату прямо в строке запроса без функции ДАТАВРЕМЯ()? Здесь важно помнить: 1С воспринимает строковые даты только в одном формате — 'ГГГГММДД' (без разделителей!). Пример:
ВЫБРАТЬ
*
ИЗ
Документ.ПоступлениеТоваров
ГДЕ
Дата = '20260515'
⚠️ Внимание: Если вы укажете дату в формате'15.05.2026'или'15-05-2026', запрос вернёт ошибку! Платформа 1С не поддерживает автоматические преобразования строковых дат с разделителями.
Для удобства можно использовать параметры запроса, которые позволяют динамически подставлять даты:
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ТекущаяДата()));
Запрос.Текст =
"ВЫБРАТЬ
ДатаДокумента,
Номер
ИЗ
Документ.ЗаказПокупателя
ГДЕ
ДатаДокумента >= &ДатаНачала";
Функции для работы с датами в запросах
Платформа 1С:Предприятие предоставляет ряд встроенных функций, которые упрощают манипуляции с датами прямо в тексте запроса. Рассмотрим самые полезные из них:
- 📅
ДАТАВРЕМЯ(Год, Месяц, День)— создаёт значение типаДатаиз числовых компонентов. Пример:ДАТАВРЕМЯ(2026, 5, 15)вернёт15.05.2026 00:00:00. - ⏰
НАЧАЛОДНЯ(Дата)— обнуляет время, оставляя только дату. Полезно для фильтрации без учёта времени:ДатаДокумента >= НАЧАЛОДНЯ(&ДатаНачала). - 📊
НАЧАЛОПЕРИОДА(Дата, ТипПериода)— возвращает первую дату периода (день, неделя, месяц, квартал, год). Пример:НАЧАЛОПЕРИОДА(ТекущаяДата(), "Месяц")вернёт01.05.2026. - 🔄
ДОБАВИТЬМЕСЯЦ(Дата, Количество)— сдвигает дату на указанное количество месяцев. Пример:ДОБАВИТЬМЕСЯЦ(ТекущаяДата(), -1)вернёт дату месячной давности.
Особого внимания заслуживает функция ВЫРАЗИТЬ(), которая позволяет преобразовывать строки в даты только если формат строки соответствует системным настройкам. Например:
ВЫБРАТЬ
ВЫРАЗИТЬ("15.05.2026" КАК ДАТА) КАК ПреобразованнаяДата
⚠️ Внимание: ФункцияВЫРАЗИТЬ()зависит от региональных настроек базы! Если в конфигурации установлен формат датыММ.ДД.ГГГГ, то строка"15.05.2026"будет интерпретирована как15 мая, а не5 ноября. Всегда проверяйте формат даты в настройках пользователя!
Чтобы избежать ошибок при работе с датами в многоязычных базах, используйте универсальный формат 'ГГГГ-ММ-ДД' в строковых литералах или параметрах. Например: ВЫРАЗИТЬ("2026-05-15" КАК ДАТА) будет корректно обработано независимо от региональных настроек.
Фильтрация по диапазону дат
Чаще всего даты в запросах используются для фильтрации документов за определённый период. Рассмотрим основные подходы:
- Фильтрация между двумя датами:
ГДЕДатаДокумента >= ДАТАВРЕМЯ(2026, 01, 01)
И ДатаДокумента <= ДАТАВРЕМЯ(2026, 12, 31)
- Использование функций начала/конца периода:
ГДЕДатаДокумента >= НАЧАЛОПЕРИОДА(ТекущаяДата(), "Месяц")
И ДатаДокумента <= КОНЕЦПЕРИОДА(ТекущаяДата(), "Месяц")
- Динамический диапазон (последние N дней):
ГДЕДатаДокумента >= ДОБАВИТЬДЕНЬ(ТекущаяДата(), -30)
Для удобства можно вынести границы периода в параметры запроса:
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", КонецМесяца(ТекущаяДата()));
Запрос.Текст =
"ВЫБРАТЬ
ДатаДокумента,
СуммаДокумента
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента МЕЖДУ &ДатаНачала И &ДатаОкончания";
☑️ Проверка корректности фильтрации по датам
Типичные ошибки при работе с датами
Даже опытные разработчики иногда допускают ошибки при указании дат в запросах. Вот самые распространённые из них:
| Ошибка | Пример | Как исправить |
|---|---|---|
| Использование неверного формата строковой даты | Дата = '15.05.2026' |
Заменить на Дата = '20260515' или Дата = ДАТАВРЕМЯ(2026, 5, 15) |
| Игнорирование времени в дате | ДатаДокумента = ТекущаяДата() (не найдёт документы с временем) |
Использовать НАЧАЛОДНЯ(ДатаДокумента) = НАЧАЛОДНЯ(ТекущаяДата()) |
| Неучёт часовых поясов в распределённых базах | Фильтрация по ТекущаяДата() в базе с серверами в разных странах |
Явно указывать часовой пояс или использовать UTC |
Путаница с функциями НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА |
КОНЕЦПЕРИОДА(Дата, "День") возвращает 00:00:00 следующего дня |
Для включения последней даты использовать <= КОНЕЦДНЯ(Дата) |
Ещё одна распространённая проблема — неявное преобразование типов. Например, если поле в базе имеет тип Дата, а вы сравниваете его со строкой, 1С может не выдавать ошибку, но результат будет некорректным. Всегда следите за соответствием типов!
Почему запрос с датой возвращает пустой результат?
Чаще всего это происходит из-за:
1. Несоответствия форматов (например, сравнение даты с временем с чистой датой без времени).
2. Ошибок в часовых поясах (актуально для распределённых баз).
3. Неверно указанных границ диапазона (например, Дата < КОНЕЦПЕРИОДА() вместо Дата <= КОНЕЦПЕРИОДА()).
4. Фильтрации по полю, которое хранит NULL вместо реальных дат.
Работа с датами в разных версиях 1С
Синтаксис работы с датами может незначительно отличаться в зависимости от версии платформы 1С:Предприятие. Например:
- 🔹 В 1С 7.7 для указания даты использовался формат
{ДД.ММ.ГГГГ}, а функции были ограничены. - 🔹 В 1С 8.0–8.2 появились функции
НАЧАЛОПЕРИОДА()иКОНЕЦПЕРИОДА(), но синтаксис параметров запроса был менее гибким. - 🔹 В 1С 8.3 добавлена поддержка
ДАТАВРЕМЯ()с миллисекундами и улучшена работа с часовыми поясами.
Для 1С 8.3 также доступны расширенные возможности по работе с датами в запросах к регистрам накопления и регистрам сведений. Например, можно использовать виртуальные таблицы с автоматическим разрезом по периодам:
ВЫБРАТЬ
Период КАК Дата,
Сумма(Количество) КАК Итого
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(,
Период С &ДатаНачала ПО &ДатаОкончания,
) КАК ОборотыТоваров
⚠️ Внимание: В версиях 1С ниже 8.3.10 функция ДОБАВИТЬМЕСЯЦ() могла некорректно обрабатывать отрицательные значения (например, при вычитании месяцев). Если вы поддерживаете устаревшие конфигурации, тестируйте такие сценарии отдельно.
Практические примеры запросов с датами
Рассмотрим несколько реальных кейсов, где явное указание даты критично для корректной работы запроса.
Пример 1: Выборка документов за текущий квартал
ВЫБРАТЬ
Номер,
ДатаДокумента,
СуммаДокумента
ИЗ
Документ.ПоступлениеТоваров
ГДЕ
ДатаДокумента >= НАЧАЛОПЕРИОДА(ТекущаяДата(), "Квартал")
И ДатаДокумента <= КОНЕЦПЕРИОДА(ТекущаяДата(), "Квартал")
Пример 2: Сравнение с датой без учёта времени
ВЫБРАТЬ
*
ИЗ
Документ.ЗаказПокупателя
ГДЕ
НАЧАЛОДНЯ(ДатаДокумента) = НАЧАЛОДНЯ(ДАТАВРЕМЯ(2026, 5, 15))
Пример 3: Динамический отчёт за последние 7 дней
Запрос.УстановитьПараметр("ДатаГраница", ДОБАВИТЬДЕНЬ(ТекущаяДата(), -7));
Запрос.Текст =
"ВЫБРАТЬ
ДатаДокумента КАК Дата,
СуммаДокумента КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента >= &ДатаГраница
УПОРЯДОЧИТЬ ПО
ДатаДокумента";
1. Соответствие форматов (строковый литерал vs. функция ДАТАВРЕМЯ).
2. Учёт времени (используйте НАЧАЛОДНЯ() для игнорирования времени).
3. Границы диапазона (включаются ли пограничные даты).
4. Региональные настройки (формат даты по умолчанию).-->
Оптимизация запросов с датами
Запросы с фильтрацией по датам могут тормозить, если не оптимизированы. Вот несколько советов для ускорения:
- 🚀 Индексируйте поля с датами. В конфигураторе проверьте, что поля
ДатаДокументаи аналогичные включены в индексы. - 📈 Используйте виртуальные таблицы для оборотов и остатков вместо ручных join’ов.
- 🔍 Сужайте диапазон дат. Вместо выборки за год берите данные поквартально или помесячно.
- 🛠 Избегайте функций над полями в WHERE. Например,
ГОД(ДатаДокумента) = 2026тормозит индексы. Лучше:ДатаДокумента >= ДАТАВРЕМЯ(2026,1,1) И ДатаДокумента < ДАТАВРЕМЯ(2026,1,1).
Для сложных отчётов рассмотрите возможность предварительной агрегации данных в регистрах сведений. Например, можно создать регистр, который будет хранить обороты по дням, и уже из него брать данные для отчётов.
FAQ: Частые вопросы по работе с датами в 1С
Как указать дату с временем в запросе?
Используйте функцию ДАТАВРЕМЯ(Год, Месяц, День, Часы, Минуты, Секунды). Пример:
ДатаДокумента = ДАТАВРЕМЯ(2026, 5, 15, 14, 30, 0)
Или строковый литерал в формате 'ГГГГММДДЧЧММСС':
ДатаДокумента = '20260515143000'
Почему запрос не находит документы за сегодняшний день?
Скорее всего, вы сравниваете дату с временем (например, ТекущаяДата()) с полем, которое хранит только дату. Используйте:
НАЧАЛОДНЯ(ДатаДокумента) = НАЧАЛОДНЯ(ТекущаяДата())
Или:
ДатаДокумента >= НАЧАЛОДНЯ(ТекущаяДата())
И ДатаДокумента < НАЧАЛОДНЯ(ДОБАВИТЬДЕНЬ(ТекущаяДата(), 1))
Как получить первый и последний день месяца в запросе?
Используйте функции НАЧАЛОПЕРИОДА() и КОНЕЦПЕРИОДА():
ПервыйДень = НАЧАЛОПЕРИОДА(ТекущаяДата(), "Месяц");
ПоследнийДень = КОНЕЦПЕРИОДА(ТекущаяДата(), "Месяц");
Для произвольной даты:
НАЧАЛОПЕРИОДА(ДАТАВРЕМЯ(2026, 5, 15), "Месяц") // 01.05.2026
КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(2026, 5, 15), "Месяц") // 31.05.2026 23:59:59
Можно ли в запросе использовать дату из переменной?
Да, через параметры запроса:
Запрос.УстановитьПараметр("МояДата", МояПеременнаяСДатой);
Запрос.Текст = "ВЫБРАТЬ * ИЗ Документ.Заказ ГДЕ Дата = &МояДата";
Или через строку запроса (менее безопасно):
ТекстЗапроса = "ВЫБРАТЬ * ИЗ Документ.Заказ ГДЕ Дата = " + Формат(МояДата, "ДЛФ=DT");
Как учесть рабочие и выходные дни в запросе?
Для этого потребуется:
- Создать регистр сведений с календарём рабочих дней.
- В запросе присоединить его к основной таблице:
ВЫБРАТЬ
Д.ДатаДокумента,
Д.СуммаДокумента
ИЗ
Документ.РеализацияТоваровУслуг КАК Д
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Календарь КАК К
ПО Д.ДатаДокумента = К.Дата
ГДЕ
К.ТипДня = ЗНАЧЕНИЕ(Перечисление.ТипыДней.Рабочий)