Работа с датами и временем в языке запросов 1С — одна из самых востребованных задач при разработке отчетов, обработок и интеграционных решений. Неправильное форматирование или сравнение временных меток может приводить к ошибкам в данных, искажению отчетности или даже сбоям в бизнес-логике. Эта статья поможет разобраться, как корректно выражать дату и время в запросах, использовать встроенные функции 1С:Предприятие 8, избегать типовых ошибок и оптимизировать производительность.
Особенность работы с временными данными в 1С заключается в том, что система хранит их в специальном внутреннем формате, а отображает — согласно региональным настройкам пользователя. Это создает дополнительные сложности при написании универсальных запросов, которые должны работать в разных конфигурациях. Мы рассмотрим не только базовый синтаксис, но и нюансы преобразования строк в даты, сравнения временных интервалов, а также приемы для работы с миллисекундами и временными зонами.
Базовый синтаксис даты и времени в запросах 1С
В языке запросов 1С дата и время представляются с помощью литералов — фиксированных значений, заключенных в одинарные кавычки. Формат записи зависит от того, что именно вы хотите указать:
- 📅 Только дата:
'2026-12-31'— год, месяц, день через дефис. Внутренне преобразуется в начало дня (00:00:00). - ⏰ Только время:
'14:30:45'— часы, минуты, секунды. В запросах используется редко, так как автоматически привязывается к текущей дате. - 📅⏰ Дата + время:
'2026-12-31 23:59:59'— комбинация через пробел. Точность до секунды. - 🕒 Текущий момент:
ТЕКУЩАЯДАТА()— функция возвращает дату и время выполнения запроса.
Важно понимать, что 1С хранит дату и время в формате DateTime, который включает миллисекунды, даже если они не указаны явно. Например, литерал '2026-01-01' внутренне будет представлен как 2026-01-01 00:00:00.000. Это влияет на сравнения и сортировку:
ВЫБРАТЬ
ДатаДокумента КАК ПолнаяДата
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента = '2026-01-01' -- Сравнивает с началом дня
Если вам нужно выбрать документы за весь день 1 января 2026 года, используйте диапазон: ДатаДокумента МЕЖДУ '2026-01-01' И '2026-01-01 23:59:59.999'. Это учтет все миллисекунды до конца дня.
Функции для работы с датой и временем
Язык запросов 1С предоставляет набор встроенных функций, которые позволяют манипулировать временными значениями прямо в SQL-подобном синтаксисе. Их использование часто предпочтительнее, чем обработка дат на стороне 1С:Предприятие, так как снижает нагрузку на сервер приложений.
| Функция | Описание | Пример использования |
|---|---|---|
ДОБАВИТЬКДАТЕ() |
Прибавляет интервал (день, месяц, год и т.д.) к дате | ДОБАВИТЬКДАТЕ(ДатаДокумента, МЕСЯЦ, 1) — прибавляет 1 месяц |
РАЗНОСТЬДАТ() |
Вычисляет разницу между двумя датами в заданных единицах | РАЗНОСТЬДАТ(ДатаОплаты, ДатаДокумента, ДЕНЬ) — дни между датами |
НАЧАЛОПЕРИОДА() |
Возвращает начало периода (день, месяц, квартал, год) | НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ) — первое число текущего месяца |
КОНЕЦПЕРИОДА() |
Возвращает конец периода (последнюю миллисекунду) | КОНЕЦПЕРИОДА(ДатаДокумента, ДЕНЬ) — 23:59:59.999 текущего дня |
ГОД() / МЕСЯЦ() / ДЕНЬ() |
Извлекает компонент даты | ГОД(ДатаДокумента) = 2026 — фильтр по году |
Одна из самых полезных функций — НАЧАЛОПЕРИОДА() с параметром СЕКУНДА. Она позволяет "обнулять" миллисекунды, что критично для сравнений:
ВЫБРАТЬ
НОМЕР КАК НомерДокумента,
НАЧАЛОПЕРИОДА(ДатаДокумента, СЕКУНДА) КАК ДатаБезМиллисекунд
ИЗ
Документ.ПоступлениеТоваров
Преобразование строк в дату и обратно
Часто данные о дате поступают в систему в виде строк (например, из внешних источников или пользовательского ввода). Для их преобразования в формат DateTime используется функция ДАТАВРЕМЯ(), которая парсит строку согласно текущим региональным настройкам. Однако этот подход чреват ошибками, если формат строки не совпадает с ожидаемым.
Безопасный способ — явно указать формат с помощью параметров:
ВЫБРАТЬ
ДАТАВРЕМЯ(СтрокаДата, "DD.MM.YYYY HH:MI:SS") КАК ПреобразованнаяДата
ИЗ
ВременнаяТаблица
- ⚠️ Ошибка формата: Если строка содержит
"31.02.2026", функция вернетNULL, а не ошибку. - 🔄 Обратное преобразование: Для конвертации даты в строку используйте
ФОРМАТ():
ВЫБРАТЬ
ФОРМАТ(ДатаДокумента, "ДФ=dd.MM.yyyy; ЧЦ=0") КАК ДатаСтрока
ИЗ
Документ.ЗаказПокупателя
Что делать если ДАТАВРЕМЯ возвращает NULL?
Проверьте:
1. Соответствие форматов (например, в строке "2026/12/31", а вы указали "DD.MM.YYYY")
2. Корректность данных (существует ли такая дата?)
3. Локальные настройки сервера 1С (они могут влиять на интерпретацию двузначных годов)
4. Используйте конструкцию ВЫРАЗИТЬ(СтрокаДата КАК ДАТА) для альтернативного преобразования.
Сравнение дат и временных интервалов
При сравнении дат в запросах 1С важно помнить про внутреннее представление времени. Например, условие ДатаДокумента = '2026-01-01' на самом деле сравнивает с диапазоном 2026-01-01 00:00:00.000 — 2026-01-01 00:00:00.000, то есть фактически выбирает документы, созданные в первую миллисекунду дня.
Для корректной выборки по диапазону используйте:
ВЫБРАТЬ
*
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента >= НАЧАЛОПЕРИОДА('2026-01-01', ДЕНЬ)
И ДатаДокумента <= КОНЕЦПЕРИОДА('2026-01-31', ДЕНЬ)
⚠️ Внимание: При сравнении дат с временной частью (ДатаВремя) всегда учитывайте миллисекунды. Например, документ с датой'2026-01-01 23:59:59.999'не попадет в выборку с условиемДатаДокумента <= '2026-01-01 23:59:59', так как последняя миллисекунда не учтена.
Для работы с временными интервалами удобно использовать функции РАЗНОСТЬДАТ() и арифметические операции:
ВЫБРАТЬ
Номер,
ДатаДокумента,
РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА(), ДатаДокумента, ДЕНЬ) КАК ДнейНазад
ИЗ
Документ.ЗаказПокупателя
ГДЕ
РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА(), ДатаДокумента, ДЕНЬ) > 30 -- Заказы старше 30 дней
Работа с временными зонами и летним временем
1С не поддерживает временные зоны напрямую в языке запросов — все даты хранятся в локальном времени сервера. Это означает, что если ваша база работает в московском времени, а филиал — во владивостокском, при обмене данными придется вручную корректировать временные метки. Для этого можно использовать функции ДОБАВИТЬКДАТЕ() с учетом разницы:
ВЫБРАТЬ
ДатаДокумента КАК ДатаМосква,
ДОБАВИТЬКДАТЕ(ДатаДокумента, ЧАС, 7) КАК ДатаВладивосток -- +7 часов
ИЗ
Документ.ПоступлениеТоваров
С летним временем ситуация еще сложнее: 1С не отслеживает исторические изменения переходов на летнее/зимнее время. Если вам нужно учитывать такие нюансы, придется:
- Создать справочник с правилами переходов для каждой временной зоны.
- Написать функцию на встроенном языке, которая будет корректировать даты с учетом этих правил.
- Использовать результат в запросе через временные таблицы или параметры.
⚠️ Внимание: При интеграции с внешними системами (например, API банков или логов оборудования) всегда уточняйте, в каком часовом поясе передаются временные метки. Несоответствие может приводить к ошибкам в отчетности на стыке дней.
Оптимизация запросов с датами
Запросы с фильтрацией по датам могут становиться "бутылочным горлышком" производительности, особенно в больших базах. Вот ключевые приемы оптимизации:
- 🚀 Индексы: Убедитесь, что поля дат проиндексированы в метаданных. Для составных индексов помещайте дату на первое место, если она чаще всего используется в фильтрах.
- 🔍 Селективность: Избегайте функций над полями дат в условиях
ГДЕ. Например,ГОД(ДатаДокумента) = 2026менее эффективен, чемДатаДокумента >= '2026-01-01' И ДатаДокумента < '2026-01-01'. - 📊 Агрегация: Для отчетов по периодам используйте
ГРУППИРОВКА ПО НАЧАЛОПЕРИОДА(ДатаДокумента, МЕСЯЦ)вместо постобработки на клиенте.
Пример оптимизированного запроса для выборки документов за текущий квартал:
ВЫБРАТЬ
Номер,
СуммаДокумента
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента >= НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), КВАРТАЛ)
И ДатаДокумента < НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(ТЕКУЩАЯДАТА(), МЕСЯЦ, 3), КВАРТАЛ)
УПОРЯДОЧИТЬ ПО
ДатаДокумента
Использованы индексированные поля дат|Функции применены к литералам, а не к полям|Диапазоны дат закрыты с обеих сторон|Для группировки по периодам использованы НАЧАЛОПЕРИОДА/КОНЕЦПЕРИОДА|Тестирование на больших объемах данных-->
Типовые ошибки и их решения
Даже опытные разработчики 1С сталкиваются с ошибками при работе с датами в запросах. Вот наиболее распространенные случаи и способы их исправления:
| Ошибка | Причина | Решение |
|---|---|---|
| Не попадают документы за последний день периода | В условии используется < '2026-01-01' вместо <= КОНЕЦПЕРИОДА() |
Заменяйте сравнения на диапазоны с НАЧАЛОПЕРИОДА() и КОНЕЦПЕРИОДА() |
ДАТАВРЕМЯ() возвращает NULL |
Несоответствие формата строки и шаблона | Проверьте формат с помощью ФОРМАТ() или используйте ВЫРАЗИТЬ() |
| Ошибка "Некорректное значение параметра" | Передача строки вместо даты в параметр запроса | Преобразуйте строку в дату на стороне 1С перед передачей в запрос |
| Медленная работа запроса | Функции над полями дат в условиях ГДЕ |
Перенесите логику в ВЫБРАТЬ или используйте временные таблицы |
Особого внимания заслуживает ошибка с миллисекундами. Например, если вы сохраняете текущее время в документ и затем пытаетесь найти его по точной дате, запрос может не вернуть результатов из-за различий в миллисекундах. Решение — обнулять миллисекунды при сохранении или сравнении:
ДатаДокумента = НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), СЕКУНДА) -- Обнуляет миллисекунды
Всегда проверяйте запросы с датами на граничных значениях: начало/конец дня, месяца, года. Используйте тестовые данные с миллисекундами, чтобы убедиться в корректности фильтрации.
Практические примеры запросов
Рассмотрим несколько реальных сценариев, где работа с датами критична для бизнес-логики.
Пример 1: Выборка документов за последние 7 дней с группировкой по дням
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(ДатаДокумента, ДЕНЬ) КАК День,
СУММА(СуммаДокумента) КАК ИтогоЗаДень
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента >= НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), ДЕНЬ) - 7
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(ДатаДокумента, ДЕНЬ)
УПОРЯДОЧИТЬ ПО
День
Пример 2: Поиск документов с просроченной оплатой (срок оплаты — 14 дней)
ВЫБРАТЬ
Номер,
ДатаДокумента,
СуммаДокумента,
РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА(), ДатаДокумента, ДЕНЬ) КАК ДнейПросрочки
ИЗ
Документ.СчетНаОплатуПокупателю
ГДЕ
СтатусОплаты = ЗНАЧЕНИЕ(Перечисление.СтатусыОплаты.НеОплачен)
И РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА(), ДатаДокумента, ДЕНЬ) > 14
Пример 3: Сравнение продаж по часам в разные дни недели
ВЫБРАТЬ
ДЕНЬНЕДЕЛИ(ДатаДокумента) КАК ДеньНедели,
ЧАС(ДатаДокумента) КАК Час,
СУММА(СуммаДокумента) КАК СуммаПродаж
ИЗ
Документ.РеализацияТоваровУслуг
ГДЕ
ДатаДокумента >= НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ)
СГРУППИРОВАТЬ ПО
ДЕНЬНЕДЕЛИ(ДатаДокумента),
ЧАС(ДатаДокумента)
УПОРЯДОЧИТЬ ПО
ДеньНедели,
Час
Эти примеры демонстрируют, как гибко можно работать с временными данными прямо в запросах, избегая постобработки на клиентской стороне.
Часто задаваемые вопросы
Как в запросе 1С получить первую и последнюю дату текущего месяца?
Используйте функции НАЧАЛОПЕРИОДА() и КОНЕЦПЕРИОДА():
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ) КАК ПервыйДеньМесяца,
КОНЕЦПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ) КАК ПоследнийДеньМесяца
Почему запрос не находит документы за сегодня, если я использую ДатаДокумента = ТЕКУЩАЯДАТА()?
Функция ТЕКУЩАЯДАТА() возвращает дату и время выполнения запроса. Для сравнения только по дате используйте:
ДатаДокумента >= НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), ДЕНЬ)
И ДатаДокумента < НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), ДЕНЬ) + 1
Как в запросе прибавить 3 рабочих дня к дате, исключая выходные?
В языке запросов 1С нет встроенной функции для рабочих дней. Вам придется:
- Создать календарь рабочих дней в справочнике.
- Использовать временные таблицы или подзапросы для проверки дней.
- Либо реализовать логику на встроенном языке после выполнения запроса.
Пример с временной таблицей:
ВЫБРАТЬ
ДатаДокумента КАК ИсходнаяДата,
(ВЫБРАТЬ МАКСИМУМ(Дата)
ИЗ (ВЫБРАТЬ ДОБАВИТЬКДАТЕ(ДатаДокумента, ДЕНЬ, 1) КАК Дата
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ДОБАВИТЬКДАТЕ(ДатаДокумента, ДЕНЬ, 2) КАК Дата
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ДОБАВИТЬКДАТЕ(ДатаДокумента, ДЕНЬ, 3) КАК Дата)
ГДЕ ДЕНЬНЕДЕЛИ(Дата) <> 6 И ДЕНЬНЕДЕЛИ(Дата) <> 7) КАК ДатаЧерез3РабочихДня
ИЗ
Документ.ЗаказПокупателя
Можно ли в запросе 1С работать с временными зонами?
Нет, язык запросов 1С не поддерживает временные зоны напрямую. Все даты хранятся в локальном времени сервера. Для работы с разными часовыми поясами придется:
- Хранить смещение временной зоны в отдельном поле.
- Корректировать даты при выборке с помощью
ДОБАВИТЬКДАТЕ(). - Использовать внешние сервисы для конвертации временных зон (например, через HTTP-запросы).
Как оптимизировать запрос, который фильтрует данные по дате и другим полям?
Следуйте этим рекомендациям:
- Поместите условие по дате первым в секции
ГДЕ— это позволит СУБД использовать индексы эффективнее. - Избегайте функций над полями дат (например,
ГОД(ДатаДокумента)). Вместо этого используйте диапазоны: - Для сложных фильтров используйте временные таблицы, чтобы разбить запрос на этапы.
- Проверьте план выполнения запроса в консоли администратора сервера 1С.
ДатаДокумента >= '2026-01-01' И ДатаДокумента < '2026-01-01'