Работа с временными метками является фундаментальной задачей при разработке сложных отчетов и обработок данных в платформе 1С:Предприятие 8. Разработчики часто сталкиваются с необходимостью фильтрации документов за сегодня, расчета возраста задолженности или простого отображения момента формирования отчета. Понимание того, как корректно извлечь текущую дату непосредственно на языке запросов, позволяет оптимизировать код и избежать лишних вызовов встроенного языка.

Система предоставляет несколько встроенных функций, каждая из которых возвращает значение с разной точностью и семантикой. Например, функция СЕГОДНЯ() отсекает время, оставляя только дату, в то время как ПОЛУЧИТЬВРЕМЯ() возвращает полный момент с точностью до секунды. Выбор конкретного метода зависит от бизнес-логики: нужно ли вам найти все документы, созданные в течение текущего дня, или только те, что появились в последнюю минуту.

Некорректное использование типов данных при сравнении дат может привести к тому, что нужные записи не попадут в выборку или, наоборот, в отчет проникнут лишние данные из прошлого или будущего. В этой статье мы подробно разберем синтаксис, особенности работы с периодами и типичные ошибки, которые допускают даже опытные специалисты при написании запросов.

Базовые функции получения даты

Самым распространенным способом получения текущей даты является вызов функции СЕГОДНЯ(). Эта функция не требует параметров и возвращает значение типа Дата, у которого время установлено в ноль часов ноль минут. Она идеально подходит для случаев, когда временная составляющая не важна, и необходимо работать с целыми сутками.

Если же ваша задача требует учета точного времени создания объекта, следует использовать функцию ПОЛУЧИТЬВРЕМЯ(). Она возвращает текущий момент времени сервера или клиента (в зависимости от контекста выполнения) с полной детализацией. Это критично важно при анализе журналов регистрации или высокочастотных операций.

💡

Всегда проверяйте часовой пояс сервера 1С, если ваш отчет выполняется в распределенной информационной базе, так как функция ПОЛУЧИТЬВРЕМЯ() вернет локальное время сервера базы данных.

Существует также функция НАЧАЛОДНЯ(), которая часто применяется в связке с другими переменными. Она принимает на вход любую дату и возвращает начало соответствующих суток. Хотя она не возвращает "текущий" момент сама по себе, в комбинации с СЕГОДНЯ() она делает код более читаемым и явным.

💡

Функция СЕГОДНЯ() возвращает дату с обнуленным временем (00:00:00), что делает её идеальной для фильтрации по суткам, но непригодной для поиска событий, произошедших несколько минут назад.

Использование даты в условиях отбора

При формировании условия ГДЕ в тексте запроса важно понимать разницу между сравнением полных дат и сравнением только их частей. Если вы напишете условие ГДЕ ДатаДокумента = СЕГОДНЯ(), то в выборку попадут только те документы, у которых время создания ровно 00:00:00. Таких документов в реальной базе данных практически не бывает.

Для корректного отбора всех документов за текущий день необходимо использовать диапазон значений. Стандартным паттерном является проверка того, что дата документа больше или равна началу сегодняшних суток и строго меньше начала завтрашних суток. Это гарантирует попадание в выборку всех записей от 00:00:00 до 23:59:59 текущего дня.

⚠️ Внимание: Никогда не используйте оператор "меньше или равно" (<=) с функцией КОНЕЦДНЯ(СЕГОДНЯ()) для отсечения лишнего времени. Из-за особенностей хранения типа Дата (точность до секунды или миллисекунды) вы можете случайно отсечь документы, созданные в последние доли секунды перед полуночью.

Пример правильного условия отбора выглядит следующим образом:

ГДЕ

Документ.Дата >= НАЧАЛОДНЯ(СЕГОДНЯ())

И Документ.Дата < НАЧАЛОДНЯ(СЕГОДНЯ() + 1)

Такой подход обеспечивает высокую производительность, так как позволяет движку базы данных эффективно использовать индексы по полю даты. Использование функций над полем таблицы (например, НАЧАЛОДНЯ(Документ.Дата)) в условии отбора может привести к полному сканированию таблицы и серьезному замедлению работы отчета.

📊 Какой метод отбора по дате вы используете чаще всего?
Равенство СЕГОДНЯ()
Диапазон от начала дня
Функция ГОД/МЕСЯЦ/ДЕНЬ
Параметр в коде 1С

Работа с периодами и смещениями

Часто в отчетности требуется получить данные не только за сегодня, но и за вчерашний день, прошлую неделю или первый день текущего месяца. Для этих целей в языке запросов 1С предусмотрены функции-конструкторы периодов, которые позволяют динамически вычислять границы интервалов.

Функция НАЧАЛОПЕРИОДА() позволяет получить начало любого стандартного периода. Вы можете указать секунду, минуту, час, день, неделю, месяц, квартал или год. Аналогично работает функция КОНЕЦПЕРИОДА(), которая возвращает последний момент указанного интервала. Эти инструменты незаменимы при построении оборотно-сальдовых ведомостей.

  • 📅 НАЧАЛОПЕРИОДА(СЕГОДНЯ(), МЕСЯЦ) — вернет первое число текущего месяца в 00:00:00.
  • 📅 КОНЕЦПЕРИОДА(СЕГОДНЯ(), КВАРТАЛ) — вернет последний день текущего квартала в 23:59:59.
  • 📅 НАЧАЛОПЕРИОДА(СЕГОДНЯ(), ГОД) — вернет 1 января текущего года.

Для получения дат в прошлом или будущем можно использовать арифметические операции над типом Дата. К дате можно прибавлять или вычитать целые числа, которые интерпретируются как количество дней. Для работы с другими интервалами (часы, минуты) используются специальные функции добавления времени.

Как получить первый день прошлой недели?

Используйте конструкцию НАЧАЛОПЕРИОДА(СЕГОДНЯ() - 7, НЕДЕЛЯ). Это сдвинет точку отсчета на неделю назад и найдет начало той недели.

Особое внимание стоит уделить функции ДОБАВИТЬКДАТЕ(). Она позволяет гибко манипулировать компонентами даты, добавляя указанное количество лет, месяцев, дней, часов, минут или секунд. Это более надежный способ, чем простые арифметические операции, особенно при переходе через високосные годы или границы месяцев.

Вычисление разницы между датами

В бизнес-задачах часто требуется не просто получить дату, а вычислить интервал между двумя событиями. Например, рассчитать количество дней просрочки платежа или возраст оборудования. Для этих целей в запросах 1С используется функция РАЗНОСТЬДАТ().

Эта функция принимает три параметра: дату начала, дату конца и единицу измерения. Единица измерения задается предопределенным значением, таким как СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ или ГОД. Результатом выполнения функции является целое число, показывающее количество полных единиц времени между датами.

Единица измерения Описание поведения Пример использования
ДЕНЬ Возвращает количество полных суток Расчет просрочки оплаты
МЕСЯЦ Учитывает переходы через годы и разную длину месяцев Расчет стажа сотрудника
МИНУТА Высокая точность для коротких интервалов Время обработки заказа
ГОД Возвращает количество полных лет Амортизация основных средств

Если разница между датами составляет 1 день и 23 часа, то при измерении в днях результат будет равен 1, а не 2. Это поведение необходимо учитывать при построении строгой логики отчетов.

☑️ Проверка корректности расчета разницы дат

Выполнено: 0 / 4

Преобразование типов и форматирование

Иногда возникает необходимость представить дату в виде строки определенного формата непосредственно в запросе. Хотя обычно форматированием занимаются на стороне клиентского приложения или в схеме компоновки данных (СКД), в самом запросе также доступны инструменты для конвертации.

Функция СТРОКА() позволяет преобразовать значение даты в строковое представление. Однако формат вывода по умолчанию может зависеть от региональных настроек пользователя или сервера. Для гарантированного получения нужного формата лучше использовать функцию ФОРМАТ(), доступную в выражениях запроса.

Пример использования форматирования для получения даты в виде "ДД.ММ.ГГГГ":

ВЫБРАТЬ

ФОРМАТ(СЕГОДНЯ(), "ДФ='dd.MM.yyyy'") КАК ДатаСтрока

ИЗ

Справочник.Номенклатура КАК Номенклатура

Использование строковых представлений дат для условий отбора или соединений (JOIN) категорически не рекомендуется. Это приводит к потере производительности, так как база данных не сможет использовать индексы по полям типа Дата. Всегда выполняйте сравнения в исходном типе данных.

⚠️ Внимание: При преобразовании строки в дату функцией ДАТА() убедитесь, что строка соответствует ожидаемому формату. Неверный формат приведет к ошибке выполнения запроса или получению пустого значения.

Нюансы работы в распределенных базах

В распределенных информационных базах (РИБ) понятие "текущая дата" может быть неоднозначным. Время на разных узлах распределенной базы может отличаться из-за рассинхронизации часов серверов или разницы в часовых поясах филиалов.

При выполнении запроса в распределенной базе функция ПОЛУЧИТЬВРЕМЯ() вернет время того узла, на котором физически выполняется запрос. Если ваш отчет формируется на центральном узле, вы получите время центра. Если же запрос выполняется локально в узле-получателе перед обменом, вы получите локальное время филиала.

Это может привести к ситуациям, когда документы, созданные "сегодня" по времени филиала, будут считаться "вчерашними" или "завтрашними" для центрального офиса. Для решения этой проблемы рекомендуется хранить в документах дополнительное поле с унифицированным временем (например, UTC) или явно учитывать часовой пояс при формировании выборок.

💡

Для синхронизации времени в распределенных базах используйте механизм регистрации изменений с привязкой к универсальному координированному времени (UTC), чтобы избежать конфликтов при обмене данными.

Кроме того, при планировании регламентных заданий в распределенной среде необходимо явно указывать, на каком узле и в какое время они должны выполняться. Слепое использование СЕГОДНЯ() в условиях отбора регламентных отчетов может привести к тому, что часть данных будет обработана дважды или не обработана вовсе.

Можно ли использовать СЕГОДНЯ() в параметрах запроса?

Да, функцию СЕГОДНЯ() можно использовать непосредственно в тексте запроса. Однако, если вы передаете дату как параметр из кода 1С, лучше вычислить её во встроенном языке и передать значением. Это делает запрос более универсальным и позволяет легче тестировать его на разных датах без изменения кода запроса.

Почему запрос с датой работает медленно?

Чаще всего причина в использовании функций над полем таблицы в условии ГДЕ (например, ГОД(Документ.Дата) = 2026). Это запрещает использование индекса. Перепишите условие на диапазон: Документ.Дата >= '20260101' И Документ.Дата < '20260101'.

Как получить дату в формате SQL для внешнего запроса?

Если вы используете встроенный язык для формирования внешнего SQL-запроса, используйте метод Формат() объекта Дата в коде 1С перед подстановкой в строку запроса. В самом запросе 1С внешние SQL-функции не поддерживаются напрямую.

В чем разница между СЕГОДНЯ() и ТЕКУЩАЯДАТА()?

В языке запросов 1С функции ТЕКУЩАЯДАТА() не существует. Есть СЕГОДНЯ() (без времени) и ПОЛУЧИТЬВРЕМЯ() (с временем). Во встроенном языке есть свойство ТекущаяДата(), которое эквивалентно ПОЛУЧИТЬВРЕМЯ().

Как обработать високосный год в запросе?

Функции работы с периодами (НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА, ДОБАВИТЬКДАТЕ) автоматически учитывают високосные годы. Вам не нужно писать дополнительную логику, достаточно использовать эти стандартные функции платформы.