В среде разработки 1С:Предприятие работа с датами является одной из самых распространенных задач. Разработчики часто сталкиваются с необходимостью сравнения дат, формирования отчетов или очистки временной составляющей от значения типа Дата. Стандартный язык платформы хранит дату как количество секунд, прошедших с начала эры, поэтому значение Теперь() всегда содержит и время, и дату.
Игнорирование временной части может привести к логическим ошибкам в алгоритмах, особенно при фильтрации документов или расчете периодов. Например, если вы сравниваете дату документа с текущей датой, документ, созданный в 10:00, может не попасть в выборку при строгом сравнении с началом дня. Именно поэтому вопрос, как получить текущую дату без времени 1с, является фундаментальным для написания качественного кода.
Существует несколько подходов к решению этой задачи, от использования встроенных функций до ручного конструирования даты. Выбор конкретного метода зависит от контекста выполнения кода, версии платформы и требований к производительности. В этой статье мы детально разберем основные способы очистки времени и приведем примеры их использования в реальных сценариях.
Использование функции НачалоДня
Самым надежным и предпочтительным способом получения даты без времени является использование встроенной функции НачалоДня(). Эта функция принимает значение типа Дата и возвращает новую дату, у которой время принудительно установлено на 00:00:00. Это стандарт де-факто в разработке под 1С:Предприятие.
При передаче в функцию значения Теперь(), система вычисляет текущий момент и отбрасывает часы, минуты и секунды. Результатом будет объект, указывающий на самую первую секунду текущих суток. Такой подход гарантирует, что вы работаете именно с календарной датой, а не с моментом времени.
ТекущаяДата = НачалоДня(Теперь());
Важно понимать, что функция НачалоДня не изменяет исходную переменную, а возвращает новое значение. Если вам нужно сохранить результат, его необходимо присвоить переменной. Это особенно полезно при формировании условий отбора в запросах, где часто требуется сравнение по дню без учета времени регистрации документа.
⚠️ Внимание: Функция
НачалоДнявозвращает дату с временем 00:00:00. Если ваша логика предполагает включение всего дня (до 23:59:59), вам может потребоваться функцияКонецДняили добавление одного дня к результату с последующим вычитанием одной секунды.
Ручное конструирование даты через Функция
Иногда разработчики предпочитают явное создание даты для большей наглядности или в специфических случаях, когда встроенные функции по каким-то причинам недоступны. Для этого используется конструктор Дата(), который позволяет задать год, месяц и день отдельно.
Чтобы получить текущую дату без времени вручную, необходимо сначала извлечь составляющие текущей даты, а затем собрать их заново, явно указав нулевые значения для времени. Этот метод более громоздкий, но он демонстрирует внутреннюю структуру типа Дата в платформе 1С.
ТекДата = Теперь();
Год = Год(ТекДата);
Месяц = Месяц(ТекДата);
День = День(ТекДата);
ДатаБезВремени = Дата(Год, Месяц, День);
В данном примере мы игнорируем параметры часа, минуты и секунды в конструкторе Дата(), так как они необязательны и по умолчанию равны нулю. Такой код легко читается, но выполняется медленнее, чем вызов одной функции НачалоДня. Используйте этот метод только если вам нужно сконструировать произвольную дату из разрозненных числовых значений.
Используйте функцию НачалоДня() вместо ручного конструирования — это повышает производительность кода и делает его более читаемым для других разработчиков.
Особенности работы с типами данных
В языке запросов 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С учитывают эти нюансы автоматически, тогда как ручные расчеты могут дать сбой.
Использование встроенных функций работы с датой гарантирует корректный учет високосных лет, переходов часовых поясов и других календарных особенностей.
⚠️ Внимание: Интерфейс и поведение некоторых функций могут меняться в новых версиях платформы 1С:Предприятие. Сверяйте синтаксис с официальной документацией для вашей конкретной версии релиза.
☑️ Проверка корректности работы с датой
В чем разница между Теперь() и ТекущаяДата()?
Функция Теперь() возвращает текущую дату и время с точностью до секунды (или миллисекунды в некоторых режимах). Функции ТекущаяДата() в стандартном встроенном языке 1С не существует, часто под ней подразумевают НачалоДня(Теперь()). Есть также контекстные свойства, например, в отчетах СКД, но в коде используйте Теперь().
Как получить вчерашнюю дату без времени?
Для этого нужно вычесть один день из текущего начала дня. Код будет выглядеть так: НачалоДня(Теперь()) - 86400 (где 86400 — количество секунд в сутках) или использовать функцию НачалоДня(Теперь() - 86400) для гарантии обнуления времени.
Можно ли хранить дату без времени в регистре сведений?
В регистрах сведений поле типа Дата всегда хранит время. Если вам нужно группировать данные по дням, храните полную дату, но при выборке и группировке используйте функцию НАЧАЛОДНЯ. Отдельного типа "Только дата" в платформе 1С нет.
Почему сравнение дат не работает, если время разное?
Потому что 25.10.2023 00:00:00 меньше, чем 25.10.2023 10:00:00. Для сравнения только календарных дней необходимо привести обе даты к началу дня с помощью функции НачалоДня() перед оператором сравнения.
Как отформатировать дату в строку без времени?
Используйте функцию Формат(). Пример: Формат(ТекущаяДата, "ДФ=dd.MM.yyyy"). Этот формат выведет только день, месяц и год, игнорируя временную часть при отображении, хотя само значение даты время все еще содержит.