Работа с датами в 1С:Предприятие часто требует преобразования типа ДатаВремя в более простой формат Дата — например, для отчетов, где время не имеет значения, или при интеграции с внешними системами. Несмотря на кажущуюся простоту задачи, нюансы синтаксиса, особенности платформы и типовые ошибки могут превратить рутинную операцию в часовой поиск решения.
В этой статье разберем все актуальные способы преобразования ДатаВремя → Дата в 1С 8.3 и 8.2, включая встроенные функции, запросы, программный код на встроенном языке и обходные пути для нестандартных ситуаций. Особое внимание уделим типовым ошибкам (например, потере данных при неявном приведении типов) и оптимизации кода для крупных баз данных.
Материал будет полезен как бухгалтерам, которые хотят самостоятельно доработать отчет, так и разработчикам, ищущим наиболее эффективное решение для обработки больших массивов данных.
1. Встроенные функции 1С для преобразования даты
Платформа 1С:Предприятие предоставляет несколько встроенных методов для работы с датами. Самые очевидные — функции НачалоДня() и Дата() — но их поведение отличается, и выбор зависит от конкретной задачи.
Функция НачалоДня(<ДатаВремя>) обнуляет временную часть, возвращая дату с временем 00:00:00. Это удобно, когда нужно сохранить тип ДатаВремя, но "сбросить" время. Например:
ДатаСВременем = НачалоДня(ТекущаяДата());
// Результат: 2026-05-20 00:00:00
Функция Дата(<Год>, <Месяц>, <День>) создает новую дату без времени, но требует явного указания компонентов. Для преобразования существующей даты-времени придется извлекать год, месяц и день:
ДатаБезВремени = Дата(Год(ТекущаяДата()), Месяц(ТекущаяДата()), День(ТекущаяДата()));
// Результат: 2026-05-20
- ✅ Плюсы: Простота, не требует дополнительных модулей.
- ⚠️ Минусы:
НачалоДня()сохраняет тип ДатаВремя, что может вызвать ошибки при сравнении с полем типа Дата. - 🔄 Альтернатива: Использовать
Формат()для строкового представления (см. раздел 3).
Если вам нужно сравнить дату-время с датой в запросе, используйте конструкцию ДАТАВРЕМЯ(Год, Месяц, День) — это ускорит выполнение на больших базах.
2. Преобразование в запросах 1С
В языке запросов 1С тип ДатаВремя автоматически не преобразуется в Дата. Чтобы получить чистую дату, используйте функцию ДАТАВРЕМЯ() с извлечением компонентов или НАЧАЛОПЕРИОДА():
Пример 1: Извлечение даты из поля Документ.Дата:
ВЫБРАТЬ
ДАТАВРЕМЯ(ГОД(Документ.Дата), МЕСЯЦ(Документ.Дата), ДЕНЬ(Документ.Дата)) КАК ДатаБезВремени
ИЗ
Документ.ПоступлениеТоваров КАК Документ
Пример 2: Использование НАЧАЛОПЕРИОДА() для обнуления времени:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Документ.Дата, "ДЕНЬ") КАК ДатаНачалоДня
ИЗ
Документ.РеализацияТоваров КАК Документ
| Метод | Синтаксис | Тип результата | Примечание |
|---|---|---|---|
ДАТАВРЕМЯ() |
ДАТАВРЕМЯ(ГОД(), МЕСЯЦ(), ДЕНЬ()) |
ДатаВремя | Время будет 00:00:00, но тип остается ДатаВремя |
НАЧАЛОПЕРИОДА() |
НАЧАЛОПЕРИОДА(Дата, "ДЕНЬ") |
ДатаВремя | Аналог НачалоДня() в языке 1С |
| Явное приведение | ДАТА(ДатаВремя) |
Дата | Работает только в новых версиях платформы (8.3.14+) |
3. Программное преобразование на встроенном языке
Для гибкой обработки дат в модулях 1С можно использовать комбинацию функций или создать собственную процедуру. Например, чтобы гарантированно получить тип Дата, используйте конструктор:
Функция ПреобразоватьВДата(ЗначениеДатаВремя)
Возврат Новый Дата(Год(ЗначениеДатаВремя), Месяц(ЗначениеДатаВремя), День(ЗначениеДатаВремя));
КонецФункции
Если требуется массовая обработка (например, в цикле по таблице значений), оптимизируйте код, избегая повторных вызовов Год()/Месяц()/День():
Для Каждого Строка Из ТаблицаДокументов Цикл
ГодТек = Год(Строка.Дата);
МесяцТек = Месяц(Строка.Дата);
ДеньТек = День(Строка.Дата);
Строка.ДатаБезВремени = Новый Дата(ГодТек, МесяцТек, ДеньТек);
КонецЦикла;
⚠️ Внимание: При неявном приведении типов (например, присваивании ДатаВремя в поле типа Дата) платформа автоматически обрезает время, но это может вызвать ошибку "Тип не соответствует типу параметра" в строго типизированных контекстах (например, при передаче в функцию).
Почему не работает приведение типов в старых версиях 1С?
В версиях платформы ниже 8.3.14 явное приведение Дата(ДатаВремя) не поддерживалось. Вместо этого использовали обходные пути:
- Создание новой даты через конструктор
Новый Дата(). - Использование
Формат(ДатаВремя, "ДФ=dd.MM.yyyy")с последующим разбором строки. - Запросы с
ДАТАВРЕМЯ(ГОД(), МЕСЯЦ(), ДЕНЬ()).
4. Преобразование через форматирование (строка → дата)
Иногда удобно преобразовать ДатаВремя в строку, а затем обратно в Дата. Это актуально, например, при обмене данными с внешними системами, где даты передаются в текстовом формате.
Пример 1: Форматирование с последующим разбором:
СтрокаДата = Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy");
ДатаРезультат = Дата(СтрокаДата);
Пример 2: Использование региональных настроек (если формат даты зависит от локали):
ФорматДаты = Формат(ТекущаяДата(), "ДЛФ=D");
ДатаРезультат = Дата(ФорматДаты);
- 📅 Плюсы: Гибкость — можно адаптировать под любой формат.
- ⚠️ Минусы: Зависимость от региональных настроек (например,
"05.06"может быть интерпретировано как 5 июня или 6 мая). - 🔧 Совет: Всегда явно указывайте формат (
"ДФ=dd.MM.yyyy"), чтобы избежать неоднозначностей.
5. Типовые ошибки и как их избежать
Ошибка 1: Потеря данных при неявном приведении.
При присваивании ДатаВремя в поле типа Дата время обрезается, но если поле имеет ограничения (например, Неопределено не допускается), это вызовет исключение.
Ошибка 2: Сравнение дат с временем.
Условие Если ДатаСВременем = ДатаБезВремени Тогда может не сработать, даже если даты совпадают, из-за ненулевого времени. Используйте НачалоДня() для обеих сторон сравнения:
Если НачалоДня(ДатаСВременем) = ДатаБезВремени Тогда
// Код
КонецЕсли;
Ошибка 3: Проблемы с часовыми поясами.
Если база работает с учетом временных зон, НачалоДня() может вернуть неожиданный результат (например, 19.05.2026 23:00:00 вместо 20.05.2026 00:00:00). В таких случаях используйте:
ДатаБезВремени = Дата(Год(ДатаСВременем), Месяц(ДатаСВременем), День(ДатаСВременем));
⚠️ Внимание: В версиях 1С:Предприятие ниже 8.3.10 функцияДата()при передаче строки с временной частью ("20.05.2026 15:30:00") может игнорировать время или вызвать ошибку. Всегда очищайте временную часть заранее.
Поле не содержит Неопределено|Учет часовых поясов отключен или скорректирован|Формат даты явно задан (например, "ДФ=dd.MM.yyyy")|Тип результата соответствует целевому полю (Дата vs ДатаВремя)
-->
6. Оптимизация для больших баз данных
При обработке тысяч записей (например, в фоне или при загрузке данных) важно минимизировать накладные расходы. Вот несколько приемов:
1. Используйте запросы вместо поэлементной обработки.
Запрос с ДАТАВРЕМЯ(ГОД(), МЕСЯЦ(), ДЕНЬ()) выполнится быстрее, чем цикл по таблице значений с вызовом Новый Дата() для каждой строки.
2. Кэшируйте промежуточные значения.
Если в цикле многократно извлекаете год/месяц/день, сохраняйте их в переменные (см. пример в разделе 3).
3. Отключайте проверку прав при массовых операциях.
Если код выполняется в привилегированном режиме (например, в фоне), используйте:
НачатьТранзакцию();
Попытка
// Ваш код с преобразованием дат
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
| Метод | Скорость (10 000 записей) | Память | Рекомендация |
|---|---|---|---|
Поэлементный Новый Дата() |
~1.2 сек | Высокая | Не использовать для больших массивов |
Запрос с ДАТАВРЕМЯ() |
~0.3 сек | Низкая | Оптимально для выборок |
Массовое НачалоДня() + приведение |
~0.8 сек | Средняя | Подходит для промежуточных расчетов |
Для массовой обработки дат всегда отдавайте предпочтение запросам — они выполняются на сервере 1С и не нагружают клиентское приложение.
7. Альтернативные подходы (для нестандартных задач)
Если стандартные методы не подходят (например, требуется преобразовать дату в негригорианском календаре или с учетом производственного календаря), рассмотрите следующие варианты:
- 📅 Использование внешних компонент:
Библиотеки вроде OneScript.DateExtensions или NativeAPI позволяют работать с датами на уровне ОС, где доступны дополнительные функции (например, преобразование в UNIX-time).
- 🔄 Обмен через JSON/XML:
При интеграции с веб-сервисами даты часто передаются в формате ISO (
"2026-05-20T00:00:00"). Для разбора используйте:ДатаРезультат = Дата(Лев(JSONСтрока, 10)); // Извлекаем "2026-05-20" - 📊 Производственный календарь:
Если нужно преобразовать дату в "рабочий день" (исключая выходные), используйте обработку с учетом календаря:
Если Не Календарь.ЭтоВыходной(ДатаБезВремени) Тогда// Логика для рабочего дня
КонецЕсли;
⚠️ Внимание: При работе с внешними компонентами проверьте их совместимость с вашей версией платформы 1С:Предприятие. Некоторые библиотеки требуют дополнительных лицензий или прав администратора для установки.
FAQ: Частые вопросы по преобразованию дат в 1С
Можно ли преобразовать ДатаВремя в Дата без потери времени?
Нет, тип Дата в 1С не хранит временную часть. Если нужно сохранить время, используйте ДатаВремя с обнуленным временем (НачалоДня()) или храните время отдельно (например, в числовом поле как количество секунд).
Почему при сравнении дат с временем и без результат Ложь?
Платформа 1С сравнивает не только дату, но и время. Например, ДатаВремя(2026, 5, 20, 15, 0, 0) = Дата(2026, 5, 20) вернет Ложь, потому что слева есть ненулевое время. Используйте НачалоДня() для обеих сторон сравнения.
Как преобразовать дату в строку с учетом региональных настроек?
Используйте параметр "ДЛФ" в функции Формат():
СтрокаДата = Формат(ТекущаяДата(), "ДЛФ=D"); // Формат по умолчанию для даты
Чтобы явно задать формат, используйте "ДФ=dd.MM.yyyy".
Работает ли Дата(ДатаВремя) в 1С 8.2?
Нет, явное приведение типа Дата(ДатаВремя) появилось только в версии 8.3.14. В 8.2 используйте конструктор Новый Дата() или функции НачалоДня().
Как преобразовать дату в UNIX-time?
В стандартной поставке 1С нет прямой функции для этого. Используйте внешнюю компоненту или рассчитайте вручную:
UNIXTime = Цел((ДатаВремя - Дата(1970, 1, 1)) * 86400);
Обратите внимание на часовые пояса!