Работа с датами в запросах 1С:Предприятие — одна из самых частых задач при разработке отчётов, обработок и аналитических выборок. Неправильно указанная дата может привести к пустому результату, ошибкам выполнения или некорректной фильтрации данных. В этой статье разберём все способы указания дат: от простых литералов до динамических параметров, а также нюансы работы с временными интервалами и функциями даты.
Особенность языка запросов 1С в том, что он поддерживает как стандартный SQL-подобный синтаксис, так и уникальные конструкции, специфичные для платформы. Например, здесь нет привычного TO_DATE() как в Oracle, но зато есть гибкие функции вроде НАЧАЛОПЕРИОДА() или КОНЕЦДНЯ(). Если вы только начинаете осваивать запросы или хотите систематизировать знания — этот материал поможет избежать типичных ошибок и оптимизировать код.
1. Базовый синтаксис: как указать дату напрямую в запросе
Самый простой способ — использовать литерал даты, который записывается в формате 'ГГГГ-ММ-ДД' или 'ГГГГ-ММ-ДД ЧЧ:ММ:СС'. Например, чтобы выбрать документы за конкретный день, достаточно написать:
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка,
Документ.Дата КАК Дата
ИЗ
Документ.ПоступлениеТоваров КАК Документ
ГДЕ
Документ.Дата = '2026-10-15'
Важно: 1С автоматически преобразует строковый литерал в тип Дата, но только если формат соответствует стандарту ISO 8601. Попытка указать дату в формате '15.10.2026' приведёт к ошибке! Также учитывайте, что время по умолчанию будет 00:00:00, если его явно не указать.
- 📅 Литерал без времени:
'2026-10-15'— соответствует началу дня (00:00:00). - ⏰ Литерал с временем:
'2026-10-15 14:30:00'— точная метка времени. - 🌍 Часовой пояс: в 1С даты хранятся без привязки к поясу, но при выводе могут корректироваться по настройкам пользователя.
⚠️ Внимание: Если в запросе используется литерал даты с временем (например,'2026-10-15 23:59:59'), а в базе данные хранятся с миллисекундами, сравнение может не сработать из-за округления. В таких случаях лучше использовать функцииНАЧАЛОДНЯ()илиКОНЕЦДНЯ().
2. Использование параметров запроса для гибкой фильтрации
Жёсткое указание даты в коде запроса не всегда удобно — часто требуется передавать её динамически из формы или переменной. Для этого в 1С предусмотрены параметры запроса, которые обозначаются символом &. Например:
ВЫБРАТЬ
Документ.Ссылка,
Документ.Дата
ИЗ
Документ.РеализацияТоваров КАК Документ
ГДЕ
Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода
Чтобы передать значение параметра из кода 1С, используйте метод УстановитьПараметр():
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ... ГДЕ Дата = &МойПараметр";
Запрос.УстановитьПараметр("МойПараметр", ТекущаяДата());
Результат = Запрос.Выполнить();
Преимущество параметров в том, что они:
- 🔄 Позволяют повторно использовать один запрос с разными данными.
- 🛡️ Защищают от SQL-инъекций (в отличие от конкатенации строк).
- ⚡ Ускоряют выполнение за счёт предварительной компиляции плана запроса.
3. Функции работы с датами в запросах 1С
1С:Предприятие предоставляет набор встроенных функций для манипуляции датами прямо в тексте запроса. Они помогают избежать ручного вычисления границ периодов или преобразования форматов. Вот ключевые из них:
| Функция | Описание | Пример использования |
|---|---|---|
ТЕКУЩАЯДАТА() |
Возвращает текущую дату и время на сервере. | ГДЕ Дата > ТЕКУЩАЯДАТА() - 30 (за последние 30 дней) |
НАЧАЛОПЕРИОДА(<Дата>, <Тип>) |
Возвращает начало периода (день, месяц, квартал, год). | НАЧАЛОПЕРИОДА(&ДатаДок, "МЕСЯЦ") |
КОНЕЦПЕРИОДА(<Дата>, <Тип>) |
Аналогично, но возвращает конец периода. | КОНЕЦПЕРИОДА(ТЕКУЩАЯДАТА(), "КВАРТАЛ") |
ДОБАВИТЬМЕСЯЦ(<Дата>, <Количество>) |
Сдвигает дату на указанное число месяцев. | ДОБАВИТЬМЕСЯЦ(&Дата, -1) (предыдущий месяц) |
Пример использования функций для выборки данных за текущий квартал:
ВЫБРАТЬ
Документ.Номер,
Документ.Сумма
ИЗ
Документ.ЗаказПокупателя КАК Документ
ГДЕ
Документ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), "КВАРТАЛ")
И КОНЕЦПЕРИОДА(ТЕКУЩАЯДАТА(), "КВАРТАЛ")
⚠️ Внимание: Функция ТЕКУЩАЯДАТА() возвращает дату и время на момент выполнения запроса, а не на момент компиляции текста. Если запрос выполняется долго, значение может отличаться от ожидаемого.
Убедиться, что тип периода ("ДЕНЬ", "МЕСЯЦ") написан заглавными буквами|
Проверить, что функция применяется к полю типа Дата, а не к строке|
Использовать НАЧАЛОПЕРИОДА/КОНЕЦПЕРИОДА для интервалов вместо ручного вычитания секунд|
Тестировать запрос с крайними датами (например, 31 декабря)
-->
4. Работа с интервалами и сравнение дат
Часто требуется выбрать данные за диапазон дат, например, за месяц или между двумя произвольными датами. Для этого используют операторы МЕЖДУ, >, < и их комбинации. Однако здесь есть нюансы:
- 📊
МЕЖДУвключает обе границы:Дата МЕЖДУ '2026-01-01' И '2026-01-31'вернёт и 1, и 31 января. - ⏳ Для выборки "с начала дня" до "конца дня" используйте:
Дата >= НАЧАЛОДНЯ(&Начало) И Дата < НАЧАЛОДНЯ(&Конец) + 86400 - 🔄 Для исключения границ:
Дата > '2026-01-01' И Дата < '2026-02-01'(январь без 1 февраля).
Типичная ошибка — забыть про время при сравнении. Например, запрос ГДЕ Дата = '2026-10-15' не вернёт документы, созданные 15 октября после 00:00:00, если в базе хранятся точные метки времени. Решение:
ГДЕ Дата >= НАЧАЛОДНЯ('2026-10-15')
И Дата < НАЧАЛОДНЯ('2026-10-16')
Почему не работает сравнение с точной датой?
При хранении даты с временем (например, '2026-10-15 14:30:00') сравнение с литералом '2026-10-15' (который эквивалентен '2026-10-15 00:00:00') вернёт ЛОЖЬ. Поэтому для выборки по календарному дню всегда используйте интервал от начала до конца дня.
5. Динамические даты: относительные периоды
В отчётах часто нужны данные за "последнюю неделю", "прошлый месяц" или "текущий квартал". Вместо жёсткого указания дат удобнее использовать относительные выражения. Например:
// За последние 7 дней (включая сегодня)
ГДЕ Дата >= ТЕКУЩАЯДАТА() - 7
// За предыдущий месяц
ГДЕ Дата МЕЖДУ НАЧАЛОПЕРИОДА(ДОБАВИТЬМЕСЯЦ(ТЕКУЩАЯДАТА(), -1), "МЕСЯЦ")
И КОНЕЦПЕРИОДА(ДОБАВИТЬМЕСЯЦ(ТЕКУЩАЯДАТА(), -1), "МЕСЯЦ")
// За текущий год
ГДЕ Дата >= НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), "ГОД")
Для более сложных сценариев (например, "последний рабочий день месяца") можно комбинировать функции:
ГДЕ Дата = КОНЕЦПЕРИОДА(ДОБАВИТЬМЕСЯЦ(ТЕКУЩАЯДАТА(), -1), "МЕСЯЦ")
Критическая особенность: функции ДОБАВИТЬМЕСЯЦ() и ДОБАВИТЬГОД() корректно обрабатывают переходы между месяцами разной длины (например, 31 января + 1 месяц = 28/29 февраля), в отличие от ручного прибавления дней.
6. Преобразование строк в даты и обратно
Иногда даты хранятся в базе как строки (например, в внешних источниках или устаревших конфигурациях). Чтобы их сравнить с полями типа Дата, нужно преобразовать формат. Для этого используйте функцию ДАТАВРЕМЯ():
ВЫБРАТЬ
Таблица.СтрокаДата КАК СтрокаДата,
ДАТАВРЕМЯ(Таблица.СтрокаДата КАК Строка, "ДФ=dd.MM.yyyy") КАК Дата
ИЗ
ВнешняяТаблица КАК Таблица
Обратное преобразование (дата в строку) выполняется функцией ФОРМАТ():
ВЫБРАТЬ
ФОРМАТ(Документ.Дата, "ДФ=dd.MM.yyyy HH:mm") КАК ФорматированнаяДата
ИЗ
Документ.Заказ КАК Документ
- 📝 Формат
"ДФ=dd.MM.yyyy"— стандартный для России. - 🌐 Для международного формата используйте
"ДФ=yyyy-MM-dd". - ⏱️ Чтобы включить время:
"ДФ=dd.MM.yyyy HH:mm:ss".
⚠️ Внимание: При преобразовании строк в даты 1С строго проверяет соответствие формату. Если строка содержит некорректные данные (например,"31.02.2026"), запрос завершится с ошибкой. Для обработки таких случаев используйте конструкциюВЫРАЗИТЬ()с проверкой:
ВЫБРАТЬ
ВЫРАЗИТЬ(ДАТАВРЕМЯ(Таблица.СтрокаДата КАК Строка, "ДФ=dd.MM.yyyy") КАК Дата) КАК Дата
ИЗ
ВнешняяТаблица КАК Таблица
ГДЕ
НЕ Таблица.СтрокаДата ЕСТЬ NULL
7. Оптимизация запросов с датами: индексы и планы выполнения
Запросы с фильтрацией по датам могут работать медленно, если:
- 🐢 Поле даты не проиндексировано в базе.
- 🔍 Используются функции над полем (например,
ГДЕ ГОД(Дата) = 2026), что блокирует использование индекса. - 📈 Диапазон дат слишком широкий (например, за 10 лет).
Рекомендации по оптимизации:
- Всегда фильтруйте по оригинальному полю даты, а не по его частям:
// Плохо (индекс не используется):ГДЕ ГОД(Дата) = 2026 И МЕСЯЦ(Дата) = 10
// Хорошо:
ГДЕ Дата МЕЖДУ '2026-10-01' И '2026-10-31'
- Для больших периодов разбивайте запрос на подзапросы или используйте
ИНДЕКСИРОВАТЬ ПО(в последних версиях платформы). - Проверяйте план выполнения запроса в Консоли запросов (меню
Все функции → План запроса).
Если запрос с датами выполняется долго, попробуйте добавить в условие И Дата < ТЕКУЩАЯДАТА() + 365 (или другой разумный лимит), чтобы ограничить диапазон поиска по умолчанию.
8. Типичные ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с неожиданными проблемами при работе с датами в 1С. Вот наиболее распространённые ошибки:
| Ошибка | Причина | Решение |
|---|---|---|
| Запрос не возвращает данные за текущий день | Сравнение с '2026-10-15' не учитывает время документа. |
Использовать НАЧАЛОДНЯ() и КОНЕЦДНЯ(). |
| Ошибка "Некорректное значение параметра" | Параметр передан как строка, а не как Дата. | Преобразовать значение: Запрос.УстановитьПараметр("Дата", Дата(СтрокаДата)). |
| Медленное выполнение на больших базах | Отсутствует индекс по полю даты или используются функции над полем. | Добавить индекс или переписать условие. |
| Неправильный результат при добавлении месяцев | Ручное прибавление дней не учитывает длину месяца. | Использовать ДОБАВИТЬМЕСЯЦ(). |
Ещё одна ловушка — разница часовых поясов. Если сервер и клиент находятся в разных поясах, ТЕКУЩАЯДАТА() на сервере может отличаться от локального времени пользователя. Чтобы избежать путаницы:
- 🕒 Явно указывайте пояс в отчётах (например, "МСК").
- 📡 Для критичных операций используйте
ТЕКУЩАЯДАТАСЕАНСА()— она возвращает дату с учётом сеанса пользователя.
Всегда тестируйте запросы с датами на граничных значениях: начало/конец месяца, високосные годы, переход на зимнее/летнее время (если актуально).
FAQ: Частые вопросы по работе с датами в запросах 1С
Как выбрать документы за вчерашний день?
Используйте комбинацию функций:
ГДЕ Дата МЕЖДУ НАЧАЛОДНЯ(ТЕКУЩАЯДАТА() - 1)
И КОНЕЦДНЯ(ТЕКУЩАЯДАТА() - 1)
Или короче:
ГДЕ Дата >= НАЧАЛОДНЯ(ТЕКУЩАЯДАТА()) - 86400
И Дата < НАЧАЛОДНЯ(ТЕКУЩАЯДАТА())
Почему запрос с параметром даты возвращает пустой результат, хотя данные есть?
Вероятные причины:
- Параметр передан как строка (например,
"15.10.2026"), а не как Дата. Проверьте тип:ТипЗнч(&ДатаПараметр) = Тип("Дата"). - В базе даты хранятся с временем, а сравнение идёт без учёта времени. Используйте
НАЧАЛОДНЯ(). - Опечатка в имени параметра (регистр важен!). Убедитесь, что в коде и тексте запроса имена совпадают.
Как выбрать данные за последний квартал, не указывая даты явно?
Используйте относительные функции:
ГДЕ Дата МЕЖДУ НАЧАЛОПЕРИОДА(ДОБАВИТЬМЕСЯЦ(ТЕКУЩАЯДАТА(), -3), "КВАРТАЛ")
И КОНЕЦПЕРИОДА(ДОБАВИТЬМЕСЯЦ(ТЕКУЩАЯДАТА(), -3), "КВАРТАЛ")
Для текущего квартала замените -3 на 0.
Можно ли в запросе 1С использовать конструкцию BETWEEN как в SQL?
Да, оператор МЕЖДУ в 1С полностью аналогичен BETWEEN в SQL и включает обе границы. Пример:
ГДЕ Дата МЕЖДУ '2026-01-01' И '2026-12-31'
Это эквивалентно:
ГДЕ Дата >= '2026-01-01' И Дата <= '2026-12-31'
Как сравнить только дату без времени, если в базе хранится ДатаВремя?
Используйте функцию НАЧАЛОДНЯ() для обеих частей сравнения:
ГДЕ НАЧАЛОДНЯ(Документ.Дата) = НАЧАЛОДНЯ('2026-10-15')
Это гарантирует, что время будет проигнорировано.