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

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

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

Использование функции НачалоДня

Самым надежным и предпочтительным способом получения даты без времени является использование встроенной функции НачалоДня(). Эта функция принимает значение типа Дата и возвращает новую дату, у которой время принудительно установлено на 00:00:00. Это стандарт де-факто в разработке под 1С:Предприятие.

При передаче в функцию значения Теперь(), система вычисляет текущий момент и отбрасывает часы, минуты и секунды. Результатом будет объект, указывающий на самую первую секунду текущих суток. Такой подход гарантирует, что вы работаете именно с календарной датой, а не с моментом времени.

ТекущаяДата = НачалоДня(Теперь());

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

⚠️ Внимание: Функция НачалоДня возвращает дату с временем 00:00:00. Если ваша логика предполагает включение всего дня (до 23:59:59), вам может потребоваться функция КонецДня или добавление одного дня к результату с последующим вычитанием одной секунды.

Ручное конструирование даты через Функция

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

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

ТекДата = Теперь();

Год = Год(ТекДата);

Месяц = Месяц(ТекДата);

День = День(ТекДата);

ДатаБезВремени = Дата(Год, Месяц, День);

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

💡

Используйте функцию НачалоДня() вместо ручного конструирования — это повышает производительность кода и делает его более читаемым для других разработчиков.

Особенности работы с типами данных

В языке запросов и в встроенном языке существуют нюансы представления дат. Тип данных Дата всегда хранит время, даже если оно равно нулю. Визуально в интерфейсе время может не отображаться, если формат поля настроен соответствующим образом, но внутри системы оно присутствует.

При сравнении двух дат, одна из которых имеет время, а другая нет, результат может быть неожиданным для новичков. Дата с временем 12:00 всегда больше даты с временем 00:00 того же дня. Поэтому перед сравнением критически важно привести оба значения к единому формату.

  • 📅 Всегда приводите даты к началу дня перед сравнением в условиях отбора.
  • ⚙️ Используйте типизированные параметры в запросах для избежания неявных преобразований.
  • 🔍 Проверяйте формат вывода даты в печатных формах, чтобы скрыть нулевое время.

Если вы работаете с данными, полученными из внешних источников (например, через HTTP-сервисы или веб-сервисы), убедитесь, что временная зона обработана корректно. Смещение времени может сдвинуть дату на предыдущий или следующий день, что нарушит логику работы с периодами.

📊 Какой метод получения даты вы используете чаще?
НачалоДня(Теперь())
Ручное создание через Дата()
Строковое преобразование
Не задумывался об этом

Обработка даты в запросах

В языке запросов платформы 1С:Предприятие также доступна функция НАЧАЛОДНЯ(). Она работает аналогично функции встроенного языка и позволяет отсечь время непосредственно на уровне базы данных. Это значительно эффективнее, чем выборка всех записей и последующая фильтрация в коде.

Использование функции в запросе позволяет оптимизировать выполнение, так как СУБД может использовать индексы по полям типа Дата более эффективно, если диапазон задан корректно. Однако следует помнить, что применение функций к полям в условии ГДЕ может иногда препятствовать использованию индексов, в зависимости от версии СУБД.

ВЫБРАТЬ

Документ.Ссылка,

Документ.Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

НАЧАЛОДНЯ(Документ.Дата) = &Период

В приведенном примере параметр &Период должен передаваться уже очищенным от времени. Если передать в параметр дату с временем, условие все равно сработает корректно благодаря функции в левой части, но лучше соблюдать чистоту данных на входе.

Функция Описание Пример результата
НачалоДня() Устанавливает время 00:00:00 25.10.2023 0:00:00
КонецДня() Устанавливает время 23:59:59 25.10.2023 23:59:59
НачалоМесяца() Первое число месяца, 00:00:00 01.10.2023 0:00:00
КонецМесяца() Последнее число месяца, 23:59:59 31.10.2023 23:59:59

⚠️ Внимание: Поведение функций времени в запросах может незначительно отличаться в зависимости от используемой СУБД (MSSQL, PostgreSQL, Oracle). Всегда тестируйте сложные временные выборки на продуктивной копии базы.

Преобразование строки в дату без времени

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

Если строка содержит только дату (например, "25.10.2023"), система автоматически подставит время 00:00:00. Однако если строка имеет формат "25.10.2023 14:30", время сохранится. Для гарантированного получения даты без времени рекомендуется комбинировать преобразование и функцию очистки.

СтрокаДаты = "25.10.2023 14:30";

ДатаИзСтроки = Дата(СтрокаДаты);

ЧистаяДата = НачалоДня(ДатаИзСтроки);

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

Что делать, если строка пустая?

Если переменная содержит пустую строку, функция Дата() вернет неопределено. Перед преобразованием всегда проверяйте строку на пустоту с помощью функции СтрДлина() или сравнением с "".

Частые ошибки при работе со временем

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

Другая ошибка — игнорирование часовых поясов при работе с распределенными базами данных или веб-клиентами. Серверное время может отличаться от времени на компьютере пользователя. Если вы получаете дату от клиента, убедитесь, что она приведена к времени сервера перед обработкой.

  • ❌ Не используйте вычитание секунд для обнуления времени — это ненадежно.
  • ✅ Всегда используйте НачалоДня для нормализации дат.
  • ⏰ Учитывайте разницу часовых поясов в распределенных системах.

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

💡

Использование встроенных функций работы с датой гарантирует корректный учет високосных лет, переходов часовых поясов и других календарных особенностей.

⚠️ Внимание: Интерфейс и поведение некоторых функций могут меняться в новых версиях платформы 1С:Предприятие. Сверяйте синтаксис с официальной документацией для вашей конкретной версии релиза.

☑️ Проверка корректности работы с датой

Выполнено: 0 / 4
В чем разница между Теперь() и ТекущаяДата()?

Функция Теперь() возвращает текущую дату и время с точностью до секунды (или миллисекунды в некоторых режимах). Функции ТекущаяДата() в стандартном встроенном языке 1С не существует, часто под ней подразумевают НачалоДня(Теперь()). Есть также контекстные свойства, например, в отчетах СКД, но в коде используйте Теперь().

Как получить вчерашнюю дату без времени?

Для этого нужно вычесть один день из текущего начала дня. Код будет выглядеть так: НачалоДня(Теперь()) - 86400 (где 86400 — количество секунд в сутках) или использовать функцию НачалоДня(Теперь() - 86400) для гарантии обнуления времени.

Можно ли хранить дату без времени в регистре сведений?

В регистрах сведений поле типа Дата всегда хранит время. Если вам нужно группировать данные по дням, храните полную дату, но при выборке и группировке используйте функцию НАЧАЛОДНЯ. Отдельного типа "Только дата" в платформе 1С нет.

Почему сравнение дат не работает, если время разное?

Потому что 25.10.2023 00:00:00 меньше, чем 25.10.2023 10:00:00. Для сравнения только календарных дней необходимо привести обе даты к началу дня с помощью функции НачалоДня() перед оператором сравнения.

Как отформатировать дату в строку без времени?

Используйте функцию Формат(). Пример: Формат(ТекущаяДата, "ДФ=dd.MM.yyyy"). Этот формат выведет только день, месяц и год, игнорируя временную часть при отображении, хотя само значение даты время все еще содержит.