Работа с временными метками является одной из самых частых задач при написании запросов в системе 1С:Предприятие. Разработчикам постоянно приходится сталкиваться с необходимостью отбора документов за конкретный месяц, расчетом остатков на начало дня или поиском операций в определенном временном интервале. Неправильное использование функций обработки дат может привести к тому, что запрос будет выполняться медленно или, что еще хуже, выдавать некорректные данные, упуская важные записи из выборки.
В языке запросов 1С существует мощный набор встроенных функций, позволяющих манипулировать объектами типа ДатаВремя. Понимание принципов их работы, особенно различий между календарными и рабочими периодами, критически важно для создания эффективного кода. В этой статье мы разберем основные методы приведения дат, способы фильтрации и типичные ошибки, которые допускают даже опытные специалисты при формировании условий отбора.
Базовые функции работы с периодами
Самой распространенной задачей является необходимость получить дату начала или конца определенного периода. Для этих целей в запросах используются функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА. Они позволяют нормализовать произвольную дату, приведенную в параметрах, до границ месяца, квартала или года. Это особенно полезно при формировании регламентных отчетов, где пользователю не важно, какого числа он запустил отчет, важно лишь, за какой месяц данные должны быть выбраны.
Функция НАЧАЛОПЕРИОДА принимает два аргумента: саму дату и уровень периода. Уровень периода задается константой, такой как Период.Месяц или Период.Год. Если вы передадите в функцию дату 15 мая 2026 года с уровнем "Месяц", результатом будет 1 мая 2026 года 00:00:00. Аналогично работает и обратная функция, которая возвращает последнюю секунду указанного периода. Использование этих функций делает код более читаемым и защищает от ошибок ручного вычисления дней в месяце.
Стоит отметить, что при работе с высокоточными временными метками важно учитывать время. По умолчанию многие функции обрезают время до начала суток, если не указано иное. Это поведение может стать причиной того, что документы, проведенные в последние секунды дня, не попадут в выборку, если условие отбора составлено некорректно. Всегда проверяйте, включает ли ваш диапазон конечную точку периода.
Используйте константу Период.День для получения точной границы суток, это исключит ошибки при переходе через полночь в отчетах с поминутной детализацией.
Преобразование строк и чисел в дату
Часто данные поступают в систему в виде строковых представлений или числовых кодов, которые необходимо преобразовать в полноценный объект даты для последующей фильтрации. В запросах 1С для этого предназначена функция ДАТАВРЕМЯ, которая собирает дату из отдельных числовых компонентов: года, месяца, дня, часа, минуты и секунды. Это позволяет конструировать даты динамически прямо внутри текста запроса.
Если же у вас есть строка формата "ДД.ММ.ГГГГ", её можно преобразовать с помощью функции ДАТА. Однако важно помнить о региональных настройках клиента и сервера. Неправильный порядок аргументов может привести к тому, что 10 января будет воспринято как 10-й месяц, что вызовет ошибку выполнения запроса или неверную выборку. Для надежности лучше использовать явное указание компонентов через ГОД, МЕСЯЦ и ДЕНЬ.
Иногда требуется получить дату из числа, представляющего количество дней от некоторой эпохи, хотя в 1С это встречается реже. В таких случаях используется арифметика дат. Вы можете прибавить или вычесть число дней из известной даты. Например, чтобы получить дату вчера, достаточно вычесть единицу из текущей даты, полученной через функцию СЕГОДНЯ. Такой подход универсален и не зависит от формата ввода данных пользователем.
Фильтрация данных по временным интервалам
Правильная организация условий отбора в секции ГДЕ напрямую влияет на производительность запроса. Использование операторов сравнения МЕЖДУ, <= и >= должно быть согласовано с типом индексов в базе данных. Наиболее эффективным способом отбора за период является использование замкнутого интервала, где четко определены границы начала и конца.
При отборе документов за месяц часто возникает дилемма: включать ли документы, проведенные в 23:59:59 последнего дня? Функция КОНЕЦПЕРИОДА по умолчанию возвращает время 23:59:59. Если в вашей базе документы могут иметь более высокую точность (например, миллисекунды), то использование строгого неравенства < с датой начала следующего месяца будет более надежным решением, чем попытка угадать последнюю секунду текущего месяца.
Рассмотрим пример конструкции условия отбора. Вместо сложных вычислений в теле запроса, лучше выносить расчет границ периода в параметры или использовать встроенные функции непосредственно в условии. Это позволяет оптимизатору запросов 1С лучше использовать индексы по полям даты. Избегайте применения функций к полям таблиц в левой части условия сравнения, так как это часто приводит к полному сканированию таблицы вместо поиска по индексу.
⚠️ Внимание: При использовании условия
ГДЕ Дата < КОНЕЦПЕРИОДА(..)убедитесь, что в базе нет документов с временем, превышающим стандартные 23:59:59, иначе они будут потеряны. Безопаснее использоватьГДЕ Дата < НАЧАЛОПЕРИОДА(СледующийМесяц).
Сравнение дат и работа с NULL
В языке запросов 1С значение NULL (или ЕСТЬNULL) играет особую роль при работе с датами. Пустая дата не равна нулю и не равна какой-либо конкретной дате. При сравнении полей, которые могут быть не заполнены, необходимо явно проверять их на наличие значения. Игнорирование этого правила — одна из самых частых причин, почему отчеты показывают меньше записей, чем ожидается.
Для обработки таких ситуаций используется функция ЕСТЬNULL. Она принимает два аргумента: проверяемое выражение и значение подмены. Если дата в поле документа не заполнена, функция вернет второе значение, которое вы можете использовать для дальнейшей логики. Например, можно подставить дату начала эпохи или текущую дату, чтобы запись гарантированно попала или не попала в выборку в зависимости от задачи.
Сравнение двух дат происходит с учетом времени. Две даты, совпадающие по календарному числу, но различающиеся на одну секунду, не будут равны друг другу. Если вам нужно сравнить даты только по календарному дню, предварительно приведите их к началу суток с помощью функции НАЧАЛОПЕРИОДА(Дата, Период.День). Это устранит влияние времени на результат логического сравнения.
☑️ Проверка условий отбора по дате
Таблица основных функций работы со временем
Для быстрого ориентирования в многообразии функций языка запросов 1С, предназначенных для манипуляций со временем, ниже приведена сводная таблица. Она поможет вам быстро подобрать нужный инструмент для конкретной задачи, будь то извлечение компонента даты или сдвиг периода.
| Функция | Описание | Пример результата |
|---|---|---|
НАЧАЛОПЕРИОДА |
Возвращает начало периода (день, месяц, год) | 01.05.2026 00:00:00 |
КОНЕЦПЕРИОДА |
Возвращает конец периода с точностью до секунды | 31.05.2026 23:59:59 |
ГОД |
Извлекает номер года из даты | 2026 |
МЕСЯЦ |
Извлекает номер месяца (1-12) | 5 |
ДАТАВРЕМЯ |
Создает дату из чисел (год, месяц, день..) | ДатаВремя(2026, 5, 20) |
Использование этих функций в комбинации позволяет решать сложные аналитические задачи. Например, группировка документов по месяцам года реализуется через функцию МЕСЯЦ в секции СГРУППИРОВАТЬ ПО.
Группировка по функциям даты (например, ПО МЕСЯЦ(Дата)) отключает использование индексов для группировки, что может замедлить запрос на больших таблицах.
Особенности работы с рабочими календарями
В задачах планирования и расчета зарплат часто требуется оперировать не календарными, а рабочими днями. Стандартные функции дат работают с календарем, игнорируя выходные и праздники. Для работы с производственными календарями в 1С существуют специальные механизмы, часто реализуемые через регистры сведений или внешние обработки, но в контексте запроса важно понимать ограничения.
Если вам нужно найти следующую рабочую дату после указанной, в чистом запросе это сделать сложно без вспомогательных таблиц. Обычно разработчики создают регистр сведений "ПроизводственныйКалендарь", где помечают рабочие и нерабочие дни. Затем в запросе делается соединение с этим регистром для фильтрации или поиска ближайшей даты. Прямое вычисление рабочего дня математическими методами в запросе невозможно из-за плавающего графика праздников.
При расчете периодов оплаты или сроков исполнения обязательств важно учитывать, что конец месяца может выпадать на выходной. В таких случаях бизнес-логика часто требует сдвига даты на первый следующий рабочий день. Реализация такой логики должна происходить на уровне приложения или через сложные вложенные запросы с использованием временных таблиц, так как одной функцией это не решить.
⚠️ Внимание: Интерфейсы и возможности работы с производственным календарем могут отличаться в разных конфигурациях (Бухгалтерия, ЗУП, УТ). Всегда сверяйте структуру регистров в вашей конкретной базе данных.
Частые ошибки и оптимизация
Одной из самых коварных ошибок является потеря точности при преобразовании типов. Например, при передаче даты из внешнего источника в строковом формате может произойти неявное приведение, которое обрежет миллисекунды. Если ваша система требует высокой точности синхронизации, всегда используйте явные функции преобразования и проверяйте результат в отладчике перед запуском на продуктивной базе.
Еще одна проблема — использование "магических чисел" вместо констант периода. Написание 30 вместо Период.Месяц делает код непонятным для других разработчиков и может привести к ошибкам, если внутренняя реализация констант изменится. Всегда используйте встроенные перечисления системы 1С для указания уровня периода в функциях времени.
Оптимизация запросов с датами также включает в себя правильный выбор типа параметра. Передавайте в запрос именно тип Дата, а не Строка, чтобы система не тратила ресурсы на конвертацию внутри СУБД. Это особенно критично для высоконагруженных систем, где счет идет на миллисекунды выполнения каждого запроса.
Секрет быстрой выборки
Если вы выбираете данные за большой период, попробуйте разбить запрос на несколько мелких по месяцам и объединить результаты. Иногда это работает быстрее одного тяжелого запроса из-за особенностей работы индексов СУБД.
Как получить текущую дату в запросе 1С?
Для получения текущей даты используется функция СЕГОДНЯ(). Она возвращает дату на момент запуска запроса с точностью до секунды. Если требуется только дата без времени, результат можно обернуть в функцию НАЧАЛОПЕРИОДА(.., Период.День).
В чем разница между ДАТА и ДАТАВРЕМЯ?
Функция ДАТА обычно используется для преобразования строки или числа в дату, часто с обрезкой времени до начала суток. Функция ДАТАВРЕМЯ позволяет явно задать все компоненты, включая часы, минуты и секунды, создавая полную временную метку.
Почему запрос не находит документы за 31 число?
Скорее всего, проблема в условии отбора. Если вы используете < (меньше) с датой начала следующего месяца, убедитесь, что время в условии корректно. Часто помогает использование <= КОНЕЦПЕРИОДА(..) или проверка времени в документах.
Можно ли вычитать даты в запросе?
Да, из даты можно вычитать число (дни) или другую дату. Результатом вычитания двух дат будет число дней между ними. Это полезно для расчета возрастов документов или длительности периодов прямо в выборке.
Как игнорировать время при сравнении дат?
Для игнорирования времени необходимо привести обе сравниваемые даты к началу суток. Используйте конструкцию НАЧАЛОПЕРИОДА(Дата, Период.День) для обоих операндов перед сравнением.