Работа с датами в запросах 1С — одна из самых востребованных задач при разработке отчётов, обработок и аналитических систем. Даты используются для фильтрации данных, группировки по периодам, расчёта временных интервалов и даже для сложных аналитических функций. Однако неопытные программисты часто сталкиваются с ошибками: неправильный формат даты, неверная фильтрация или неэффективные конструкции, которые тормозят выполнение запроса.
В этой статье мы разберём все аспекты работы с датами в языке запросов 1С — от базового синтаксиса до оптимизации сложных конструкций. Вы узнаете, как правильно указывать даты в условиях ГДЕ, использовать функции для работы с временными интервалами, избегать типовых ошибок и ускорять выполнение запросов. Материал будет полезен как начинающим разработчикам, так и опытным специалистам, которые хотят систематизировать свои знания.
Особое внимание уделим скрытым нюансам формата дат в 1С 8.3, которые часто становятся причиной ошибок при миграции кода между разными версиями платформы или при интеграции с внешними системами. Все примеры приведены с учётом актуальных требований платформы и проверены на совместимость с последними релизами.
1. Базовый синтаксис: как указать дату в запросе 1С
Самый простой способ задать дату в запросе — использовать литерал даты в формате 'ГГГГ-ММ-ДД'. Например, чтобы выбрать документы за конкретный день, пишем:
ВЫБРАТЬ
Документ.Ссылка КАК Ссылка,
Документ.Дата КАК ДатаДокумента
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
Документ.Дата = ДАТАВРЕМЯ(2026, 05, 15)
Обратите внимание: функция ДАТАВРЕМЯ() более надёжна, чем строковый литерал, так как автоматически преобразует значение в внутренний формат 1С. Альтернативный вариант — использование параметра запроса:
ЗАПРОС.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата()));
Это особенно удобно, когда дата формируется динамически в коде программы. Главное правило: никогда не передавайте даты в запрос как строки без явного приведения типа — это чревато ошибками при изменении региональных настроек базы.
- 📅 Литерал даты:
'2026-05-15'— простой, но зависит от настроек языка - ⏰ Функция ДАТАВРЕМЯ():
ДАТАВРЕМЯ(2026, 5, 15, 0, 0, 0)— надёжнее для серверных запросов - 🔄 Параметры запроса:
УстановитьПараметр("ДатаОт", НачалоМесяца(ТекущаяДата()))— лучший выбор для динамических дат
ГДЕ Документ.Дата = НАЧАЛОДНЯ(ДАТАВРЕМЯ(2026, 5, 15))-->
2. Фильтрация по диапазону дат: между, больше/меньше, в списке
Чаще всего даты используются для отбора документов за определённый период. Рассмотрим основные способы фильтрации:
1. Диапазон между двумя датами (включительно):
ГДЕ Документ.Дата МЕЖДУ ДАТАВРЕМЯ(2026, 01, 01)
И ДАТАВРЕМЯ(2026, 01, 31)
2. Отбор по "больше/меньше" (исключая граничные даты):
ГДЕ Документ.Дата >= ДАТАВРЕМЯ(2026, 01, 01)
И Документ.Дата < ДАТАВРЕМЯ(2026, 02, 01)
3. Даты в списке (например, только по понедельникам):
ГДЕ ДЕНЬНЕДЕЛИ(Документ.Дата) В (1) // 1 = понедельник
Важный нюанс: при работе с МЕЖДУ граничные даты включаются в результат, тогда как при использовании >= и < верхняя граница исключается. Это часто становится причиной ошибок в отчётах, где важна точность границ периода.
| Конструкция | Пример | Включает границы? | Применение |
|---|---|---|---|
МЕЖДУ ... И ... |
МЕЖДУ '2026-01-01' И '2026-01-31' |
Да | Отчёты за полный месяц |
>= и < |
>= '2026-01-01' И < '2026-02-01' |
Нет (верхняя) | Аналитика по дням без наложения |
ДЕНЬНЕДЕЛИ() В () |
ДЕНЬНЕДЕЛИ(Дата) В (1, 7) |
— | Фильтр по дням недели |
3. Функции для работы с датами в запросах 1С
Язык запросов 1С предоставляет богатый набор функций для манипуляции датами. Вот самые полезные из них:
- 📆 НАЧАЛОПЕРИОДА() — возвращает начало дня/недели/месяца/квартала/года:
НАЧАЛОПЕРИОДА(Документ.Дата, "МЕСЯЦ") - ⏳ КОНЕЦПЕРИОДА() — аналог
НАЧАЛОПЕРИОДА, но для конца периода:КОНЕЦПЕРИОДА(ДАТАВРЕМЯ(2026, 5, 15), "КВАРТАЛ") - 🔄 ДОБАВИТЬКДАТЕ() — прибавляет дни/месяцы/годы:
ДОБАВИТЬКДАТЕ(Документ.Дата, "ДЕНЬ", 7) - 📊 РАЗНОСТЬДАТ() — вычисляет разницу между датами в днях/месяцах:
РАЗНОСТЬДАТ("ДЕНЬ", Документ.Дата, ТЕКУЩАЯДАТА())
Особенно полезна функция НАЧАЛОПЕРИОДА() для группировки данных по календарным периодам. Например, чтобы получить продажи по месяцам:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Документ.Дата, "МЕСЯЦ") КАК Месяц,
СУММА(Документ.СуммаДокумента) КАК Итого
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(Документ.Дата, "МЕСЯЦ")
Как работают функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА с кварталами?
Функция НАЧАЛОПЕРИОДА(Дата, "КВАРТАЛ") возвращает первую дату квартала (1 января, 1 апреля, 1 июля или 1 октября), а КОНЕЦПЕРИОДА() — последнюю (31 марта, 30 июня и т.д.). Важно: в 1С кварталы всегда считаются с января, независимо от налогового периода организации.
При работе с ДОБАВИТЬКДАТЕ() будьте осторожны: при добавлении месяцев функция корректно обрабатывает конец месяца. Например, ДОБАВИТЬКДАТЕ('2026-01-31', "МЕСЯЦ", 1) вернёт '2026-02-29' (а не 31 февраля!).
Функции НАЧАЛОПЕРИОДА() и КОНЕЦПЕРИОДА() — самый надёжный способ группировки по календарным интервалам, так как они учитывают все нюансы календаря (включая високосные годы).
4. Типовые ошибки при работе с датами и как их избежать
Даже опытные разработчики иногда допускают ошибки при работе с датами в запросах. Вот наиболее распространённые проблемы и их решения:
⚠️ Внимание: Если вы используете строковые литералы дат ('2026-05-15') без явного приведения типа, запрос может работать неправильно при изменении региональных настроек сервера 1С. Всегда используйтеДАТАВРЕМЯ()или параметры.
- ❌ Сравнение даты со строкой:
Ошибка:
ГДЕ Документ.Дата = "15.05.2026"Правильно:
ГДЕ Документ.Дата = ДАТАВРЕМЯ(2026, 5, 15) - ❌ Неучёт времени в датах:
Ошибка:
ГДЕ Документ.Дата = ТЕКУЩАЯДАТА()(не сработает для документов, созданных сегодня после 00:00)Правильно:
ГДЕ НАЧАЛОДНЯ(Документ.Дата) = НАЧАЛОДНЯ(ТЕКУЩАЯДАТА()) - ❌ Неверный порядок аргументов в ДАТАВРЕМЯ():
Ошибка:
ДАТАВРЕМЯ(15, 5, 2026)(день-месяц-год вместо год-месяц-день)Правильно:
ДАТАВРЕМЯ(2026, 5, 15)
Ещё одна распространённая проблема — несоответствие типов при сравнении. Например, если поле в базе имеет тип "Дата", а вы сравниваете его с параметром типа "Строка", 1С не выдаст ошибку, но результат будет некорректным. Всегда проверяйте типы полей в метаданных!
Все даты заданы через ДАТАВРЕМЯ() или параметры|Учтено время при сравнении дат (НАЧАЛОДНЯ)|Правильный порядок аргументов в функциях|Типы сравниваемых полей совпадают-->
5. Оптимизация запросов с датами: индексы и производительность
Запросы с фильтрацией по датам могут тормозить, если не учтены особенности работы СУБД. Вот ключевые правила оптимизации:
1. Используйте индексы. Поля, по которым идёт фильтрация или сортировка по датам, должны быть проиндексированы. В 1С индексы создаются автоматически для полей типа "Дата", но при сложных условиях может потребоваться ручная настройка.
2. Избегайте функций над полями в условии. Например, вместо:
ГДЕ МЕСЯЦ(Документ.Дата) = 5
лучше написать:
ГДЕ Документ.Дата >= ДАТАВРЕМЯ(2026, 5, 1)
И Документ.Дата < ДАТАВРЕМЯ(2026, 6, 1)
3. Ограничивайте объём выборки. Если вам нужны только документы за последний месяц, не запрашивайте весь регистр:
ГДЕ Документ.Дата >= НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА())
Для анализа производительности используйте ПЛАН ВЫПОЛНЕНИЯ в консоли запросов (Ctrl+Shift+Q). Это поможет выявить "узкие места".
| Антипаттерн | Проблема | Оптимизированный вариант |
|---|---|---|
ГДЕ ГОД(Дата) = 2026 |
Функция над полем блокирует использование индекса | ГДЕ Дата >= '2026-01-01' И Дата < '2026-01-01' |
ГДЕ ДЕНЬ(Дата) = 15 |
Полное сканирование таблицы | ГДЕ Дата >= '2026-05-15' И Дата < '2026-05-16' |
| Выборка за 10 лет без ограничений | Перегрузка памяти | Разбивка на периоды или использование ПЕРВЫЕ 1000 |
ГДЕ Документ.Дата >= ДОБАВИТЬКДАТЕ(ТЕКУЩАЯДАТА(), "ДЕНЬ", -30)
Это эффективнее, чем вычислять разницу дат в условии.-->
6. Сложные сценарии: работа с временными интервалами и календарями
Иногда требуется учитывать нестандартные календари (например, рабочие дни) или сложные временные интервалы. Рассмотрим несколько нетривиальных задач:
1. Отбор только по рабочим дням (исключая выходные):
ГДЕ ДЕНЬНЕДЕЛИ(Документ.Дата) НЕ В (6, 7) // 6=суббота, 7=воскресенье
2. Фильтрация по "рабочему времени" (например, с 9:00 до 18:00):
ГДЕ Документ.Дата >= ДАТАВРЕМЯ(2026, 5, 15, 9, 0, 0)
И Документ.Дата < ДАТАВРЕМЯ(2026, 5, 15, 18, 0, 0)
3. Расчёт количества рабочих дней между датами (требует кастомизации):
// Пример с использованием виртуальной таблицы календаря
ВЫБРАТЬ
РАЗНОСТЬДАТ("ДЕНЬ", Документ.ДатаНачала, Документ.ДатаОкончания) + 1 -
(ВЫБОР
КОГДА ДЕНЬНЕДЕЛИ(Документ.ДатаНачала) = 6 ТОГДА 1
КОГДА ДЕНЬНЕДЕЛИ(Документ.ДатаНачала) = 7 ТОГДА 1
ИНАЧЕ 0
КОНЕЦ) КАК РабочиеДни
...
Для точного учёта праздников придётся создать справочник "Производственный календарь" и связать его с запросом через временную таблицу. Это актуально для расчёта зарплаты, графиков работы или логистических задач.
Как учитывать региональные праздники?
Если в вашей организации действуют региональные праздничные дни (например, в Татарстане — Ураза-Байрам), создайте справочник "ПраздничныеДни" с полем "Дата" и используйте его в запросе:
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ПраздничныеДни КАК Праздники ПО Документ.Дата = Праздники.Дата
ГДЕ Праздники.Ссылка ЕСТЬ NULL
7. Интеграция с внешними системами: форматы дат и конвертация
При обмене данными между 1С и внешними системами (например, Excel, SQL-базами или REST API) часто возникают проблемы с форматами дат. Основные правила:
- 🔄 Из 1С во внешнюю систему:
Используйте
Формат(Дата, "ДФ=yyyy-MM-dd")для универсального строкового представления. - 📅 Из внешней системы в 1С:
Для строковых дат применяйте
ДАТАВРЕМЯ(Год, Месяц, День)после парсинга. - 🗃️ Обмен с SQL:
В Microsoft SQL Server используйте
CONVERT(DATETIME, '2026-05-15', 120).
Пример конвертации даты из строки в формате DD.MM.YYYY:
Дата = ДАТАВРЕМЯ(
ЧИСЛО(ЛЕВ(СтрокаДата, 2)), // День
ЧИСЛО(СРЕД(СтрокаДата, 4, 2)), // Месяц
ЧИСЛО(ПРАВ(СтрокаДата, 4)) // Год
);
⚠️ Внимание: При обмене с Excel помните, что там даты хранятся как числа (количество дней с 1900 года). Используйте формулу=ДАТАЗНАЧ("15.05.2026")в Excel или функциюДАТАВРЕМЯ()в 1С для корректного преобразования.
Для автоматизации обмена рекомендуем создать универсальную функцию-конвертер, которая будет учитывать форматы всех интегрируемых систем. Пример:
Функция СтрокаВДату(Значение, Формат = "DD.MM.YYYY") Экспорт
// Реализация парсинга строки в дату с учётом формата
КонецФункции
8. Практические примеры: готовые запросы для типовых задач
Разберём несколько готовых запросов, которые пригодятся в повседневной работе:
1. Продажи по дням за текущий месяц:
ВЫБРАТЬ
НАЧАЛОДНЯ(Документ.Дата) КАК Дата,
СУММА(Документ.СуммаДокумента) КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
Документ.Дата >= НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА())
И Документ.Дата < КОНЕЦМЕСЯЦА(ТЕКУЩАЯДАТА()) + 1
СГРУППИРОВАТЬ ПО
НАЧАЛОДНЯ(Документ.Дата)
УПОРЯДОЧИТЬ ПО
Дата
2. Среднее время обработки заказов:
ВЫБРАТЬ
СРЕДНЕЕ(
РАЗНОСТЬДАТ(
"ЧАС",
Документ.Дата,
Документ.ДатаОплаты
)
) КАК СреднееВремяОбработки
3. Товары, не продававшиеся более 30 дней:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Товар.Ссылка КАК Товар
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товар
ГДЕ
Товар.Ссылка НЕ В (
ВЫБРАТЬ РАЗЛИЧНЫЕ Товары.Ссылка
ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ Товары.Документ.Дата >= ТЕКУЩАЯДАТА() - 30
)
4. Документы, созданные в выходные:
ВЫБРАТЬ
Документ.Ссылка,
Документ.Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
ДЕНЬНЕДЕЛИ(Документ.Дата) В (6, 7) // 6=суббота, 7=воскресенье
Эти запросы можно использовать как основу для своих отчётов. Не забывайте адаптировать их под свою конфигурацию (именование полей и таблиц может отличаться!).
Для ускорения повторяющихся отчётов сохраняйте часто используемые запросы в общих модулях или хранимых процедурах (если используется SQL-сервер).
FAQ: Ответы на частые вопросы
Как в запросе 1С получить первую и последнюю дату месяца?
Используйте функции НАЧАЛОМЕСЯЦА() и КОНЕЦМЕСЯЦА():
ВЫБРАТЬ
НАЧАЛОМЕСЯЦА(ТЕКУЩАЯДАТА()) КАК ПервыйДень,
КОНЕЦМЕСЯЦА(ТЕКУЩАЯДАТА()) КАК ПоследнийДень
Для произвольной даты замените ТЕКУЩАЯДАТА() на нужное значение.
Почему запрос с условием по дате работает медленно?
Чаще всего это связано с:
- Отсутствием индекса на поле с датой;
- Использованием функций над полем в условии (например,
ГОД(Дата) = 2026); - Слишком большим периодом выборки (запросите только нужные данные).
Проверьте план выполнения запроса (Ctrl+Shift+Q) для точной диагностики.
Как в запросе получить текущую дату без времени?
Используйте комбинацию НАЧАЛОДНЯ(ТЕКУЩАЯДАТА()):
ГДЕ Документ.Дата >= НАЧАЛОДНЯ(ТЕКУЩАЯДАТА())
И Документ.Дата < НАЧАЛОДНЯ(ТЕКУЩАЯДАТА()) + 86400 // +1 день в секундах
Или проще:
ГДЕ НАЧАЛОДНЯ(Документ.Дата) = НАЧАЛОДНЯ(ТЕКУЩАЯДАТА())
Можно ли в запросе 1С сравнивать даты с учётом часового пояса?
В стандартных запросах 1С часовые пояса не учитываются — все даты хранятся в локальном времени сервера. Для работы с часовыми поясами потребуется:
- Хранить смещение в отдельном поле;
- Использовать внешние обработки или расширения;
- Для 1С:Enterprise рассмотреть механизм
ВременнаяЗона(доступен в последних версиях).
Как в запросе получить количество дней между двумя датами?
Используйте функцию РАЗНОСТЬДАТ():
ВЫБРАТЬ
РАЗНОСТЬДАТ("ДЕНЬ", Документ.ДатаНачала, Документ.ДатаОкончания) КАК КоличествоДней
Для рабочих дней потребуется дополнительная логика (см. раздел про сложные сценарии).