Работа с датами в 1С:Предприятие — одна из самых востребованных задач при разработке конфигураций, написании отчётов и обработок. Даты используются везде: от фильтрации документов до расчёта просроченных задолженностей. Однако даже опытные программисты иногда сталкиваются с нюансами, когда нужно не просто получить текущую дату, а, например, задать конкретное значение с учётом часового пояса или преобразовать строку в дату без ошибок.
В этой статье разберём 5 основных способов задания дат в коде 1С, включая редко документированные приёмы. Особое внимание уделим типичным ошибкам, которые приводят к сбоям в расчётах, а также покажем, как избежать проблем с форматами при обмене данными между системами. Если вы когда-нибудь получали ошибку Ошибка приведение значения к типу Дата — здесь найдёте решение.
Материал будет полезен как начинающим разработчикам, так и администраторам, которые поддерживают типовые конфигурации (1С:Бухгалтерия, 1С:ЗУП, 1С:УТ). Все примеры кода протестированы на платформе 1С:Предприятие 8.3 (актуальные релизы), но majority приёмов работают и в более ранних версиях.
1. Базовые способы задания даты в 1С
Начнём с простейших методов, которые покрывают 80% задач. В 1С дата — это отдельный тип данных (Тип("Дата")), и работать с ним можно несколькими способами.
Самый очевидный вариант — прямое присваивание через конструктор Дата(год, месяц, день). Этот метод подходит, когда нужно жёстко задать фиксированную дату в коде:
МояДата = Дата(2026, 12, 31); // Последний день 2026 года
Сообщить(МояДата);
Второй базовый способ — использование текущей даты системы. Для этого есть функция ТекущаяДата(), которая возвращает дату и время на момент выполнения кода:
Сейчас = ТекущаяДата();
Сообщить("Сегодня: " + Формат(Сейчас, "ДФ=dd.MM.yyyy"));
Обратите внимание на функцию Формат() — она позволяет отобразить дату в нужном виде. Без неё в сообщении вы увидите внутреннее представление даты (например, 20260315120000), что не всегда удобно для пользователя.
- 📅 Конструктор
Дата()— для фиксированных дат (например, дата начала отчётного периода). - ⏰
ТекущаяДата()— для динамических расчётов (например, проверка актуальности цен). - 🔄
НачалоДня()/КонецДня()— для работы с временными интервалами (подробнее в следующем разделе).
Если вам нужно получить дату без времени (например, для сравнения только календарных дней), используйте конструкцию НачалоДня(ТекущаяДата()). Это обрежет часы, минуты и секунды, оставив только дату.
2. Работа с временем: начало и конец дня, сдвиги
Часто требуется не просто дата, а конкретный момент времени — начало или конец дня, недели, месяца. Для этого в 1С есть специализированные функции:
НачалоДня(Дата) — возвращает дату с временем 00:00:00. Полезно для фильтрации документов "с начала дня":
НачалоТекущегоДня = НачалоДня(ТекущаяДата());
Запрос.Текст = "ВЫБРАТЬ * ИЗ Документ.ЗаказПокупателя ГДЕ Дата >= &НачалоДня";
Запрос.УстановитьПараметр("НачалоДня", НачалоТекущегоДня);
КонецДня(Дата) — устанавливает время в 23:59:59. Применяется для условий "до конца дня":
КонецТекущегоДня = КонецДня(ТекущаяДата());
Если ТекущийДокумент.Дата <= КонецТекущегоДня Тогда
// Действие для документов сегодняшнего дня
КонецЕсли;
Для сдвига даты на заданное количество дней используйте ДобавитьМесяц(), ДобавитьДень() и аналогичные функции. Например, чтобы получить дату через 7 дней:
ДатаЧерезНеделю = ТекущаяДата() + 7; // Короткая запись
// Или явный вызов:
ДатаЧерезНеделю = ДобавитьДень(ТекущаяДата(), 7);
⚠️ Внимание: При сложении дат с использованием оператора+результат зависит от региональных настроек. В некоторых конфигурациях это может привести к ошибкам. Для надёжности используйте явные функции вродеДобавитьДень().
| Функция | Пример использования | Результат |
|---|---|---|
НачалоДня() |
НачалоДня(Дата(2026, 5, 15, 14, 30)) |
15.05.2026 00:00:00 |
КонецДня() |
КонецДня(Дата(2026, 5, 15)) |
15.05.2026 23:59:59 |
ДобавитьДень() |
ДобавитьДень(Дата(2026, 5, 15), 3) |
18.05.2026 00:00:00 |
ДобавитьМесяц() |
ДобавитьМесяц(Дата(2026, 12, 15), 1) |
15.01.2026 00:00:00 |
3. Преобразование строк в дату и обратно
Одна из самых распространённых ошибок — попытка присвоить дате значение из строки без преобразования. Например, такой код вызовет исключение:
Неверно = "15.05.2026"; // Это строка!
МояДата = Неверно; // Ошибка: нельзя присвоить строку переменной типа Дата
Для корректного преобразования используйте функцию ДатаЗнач() (или Дата() с разбором строки). Пример:
СтрокаДаты = "15.05.2026";
МояДата = ДатаЗнач(СтрокаДаты); // Автоматический разбор по региональным настройкам
Сообщить(МояДата);
Если формат строки нестандартный (например, "2026-05-15" или "15/05/2026"), используйте параметр формата:
МояДата = ДатаЗнач("2026-05-15", "ДФ=yyyy-MM-dd");
МояДата2 = ДатаЗнач("15/05/2026", "ДФ=dd/MM/yyyy");
Обратное преобразование (дата → строка) выполняется функцией Формат():
СтрокаДаты = Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy");
// Результат: "15.05.2026" (если сегодня 15 мая)
- 🔤
ДатаЗнач(Строка)— автоматически разбирает строку по региональным настройкам. - 📝
Формат(Дата, "ДФ=...")— преобразует дату в строку с заданным форматом. - ⚠️ Ошибка формата — если строка не соответствует ожидаемому формату, возникнет исключение.
Что делать, если ДатаЗнач() возвращает неверную дату?
Если функция ДатаЗнач() неправильно интерпретирует строку (например, путает день и месяц), явным образом укажите формат:
// Для строки "05-15-2026" (месяц-день-год)
ДатаЗнач("05-15-2026", "ДФ=MM-dd-yyyy");
Также проверьте региональные настройки в конфигураторе (Сервис → Параметры → Язык и региональные стандарты).
4. Работа с датами в запросах 1С
В языке запросов 1С даты используются для фильтрации, группировки и сортировки данных. Главное правило: в запросах даты передаются как параметры, а не подставляются напрямую в текст. Это защищает от ошибок и SQL-инъекций.
Пример корректного запроса с фильтрацией по дате:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Документ.ЗаказПокупателя.Ссылка КАК Ссылка,
| Документ.ЗаказПокупателя.Дата КАК Дата
|ИЗ
| Документ.ЗаказПокупателя КАК Документ
|ГДЕ
| Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата() - 7)); // Неделя назад
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ТекущаяДата()));
Результат = Запрос.Выполнить();
Особенности работы с датами в запросах:
- Для сравнения дат без времени используйте
НачалоДня()иКонецДня(). - Оператор
МЕЖДУвключает обе границы (>= И <=). - Для группировки по периодам (месяц, квартал) используйте функции
НАЧАЛОПЕРИОДА()иГОД().
⚠️ Внимание: Если в запросе используете дату с временем (например,ТекущаяДата()без обрезки), учтите, что сравнениеДата = ТекущаяДата()может не сработать из-за миллисекунд. Всегда обрезайте время функциейНачалоДня().
Использованы параметры (&Параметр) вместо жёсткого кода
Даты обрезаны до начала/конца дня при необходимости
Учтён часовой пояс (если работаете с распределёнными базами)
Проверен формат даты в результатах запроса-->
5. Работа с часовыми поясами и UTC
В распределённых системах или при интеграции с внешними сервисами часто приходится учитывать часовые пояса. По умолчанию 1С работает с локальным временем сервера, но платформа поддерживает и UTC.
Чтобы получить текущую дату в UTC:
ДатаUTC = ТекущаяУниверсальнаяДатаВремя();
Сообщить(Формат(ДатаUTC, "ДФ=dd.MM.yyyy ЧЧ:мм:сс"));
Для преобразования между локальным временем и UTC используйте функции:
// Локальное время → UTC
ЛокальнаяДата = ТекущаяДата();
ДатаUTC = ВУниверсальноеВремя(ЛокальнаяДата);
// UTC → локальное время
ЛокальнаяДатаИзUTC = ИзУниверсальногоВремени(ДатаUTC);
Если вам нужно работать с конкретным часовым поясом (например, Europe/Moscow), используйте объект ЧасовыеПояса:
ЧасовыеПояса = Новый ЧасовыеПояса;
МскПояс = ЧасовыеПояса.ПоИмени("Europe/Moscow");
ДатаВМск = ВДругомЧасовомПоясе(ТекущаяДата(), МскПояс);
- 🌍
ТекущаяУниверсальнаяДатаВремя()— возвращает дату/время вUTC. - ⏳
ВУниверсальноеВремя()/ИзУниверсальногоВремени()— конвертация между локальным временем иUTC. - 🕒 Часовые пояса — актуальны для распределённых баз или облачных решений.
⚠️ Внимание: При работе сUTCучитывайте, что некоторые функции (например,НачалоДня()) могут вести себя неожиданно. Всегда проверяйте результат на тестовых данных.
6. Типичные ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с ошибками при работе с датами. Рассмотрим самые распространённые случаи и способы их решения.
Ошибка 1: Сравнение дат с временем
Если сравнивать даты с учётом времени (например, ТекущаяДата()), результат может быть неожиданным из-за миллисекунд. Решение — обрезать время:
// Неправильно:
Если Документ.Дата = ТекущаяДата() Тогда // Может не сработать из-за времени
// Правильно:
Если НачалоДня(Документ.Дата) = НачалоДня(ТекущаяДата()) Тогда
Ошибка 2: Неверный формат строки
При преобразовании строки в дату (ДатаЗнач()) формат должен совпадать с региональными настройками. Если строка в формате "2026/05/15", а система ожидает "15.05.2026", возникнет ошибка. Решение — явное указание формата:
ДатаЗнач("2026/05/15", "ДФ=yyyy/MM/dd");
Ошибка 3: Арифметика с датами
При сложении/вычитании дат учитывайте, что результат зависит от типа операндов. Например:
Дата1 = Дата(2026, 5, 15);
Дата2 = Дата1 + 1; // Добавит 1 день → 16.05.2026
Дата3 = Дата1 + 0.5; // Добавит 12 часов → 15.05.2026 12:00:00
Критическая особенность: при вычитании двух дат результат возвращается в днях (дробное число, где дробная часть — время). Например, КонецДня(Дата1) - НачалоДня(Дата1) вернёт ~0.99999, а не 1.
Всегда обрезайте время функцией НачалоДня() перед сравнением дат, если вам важна только календарная дата без времени.
7. Практический пример: фильтрация документов по дате
Рассмотрим типовую задачу: нужно выбрать все документы "Поступление товаров" за текущий месяц. Вот как это сделать корректно:
1. Получим начало и конец текущего месяца:
ПервыйДеньМесяца = НачалоМесяца(ТекущаяДата());
ПоследнийДеньМесяца = КонецМесяца(ТекущаяДата());
2. Сформируем запрос с фильтрацией:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
| ПоступлениеТоваровУслуг.Дата КАК Дата,
| ПоступлениеТоваровУслуг.СуммаДокумента КАК Сумма
|ИЗ
| Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
|ГДЕ
| ПоступлениеТоваровУслуг.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца";
Запрос.УстановитьПараметр("НачалоМесяца", НачалоДня(ПервыйДеньМесяца));
Запрос.УстановитьПараметр("КонецМесяца", КонецДня(ПоследнийДеньМесяца));
Результат = Запрос.Выполнить();
3. Обработаем результат (например, выведем в таблицу):
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Формат(Выборка.Дата, "ДФ=dd.MM.yyyy") + " - " + Выборка.Сумма);
КонецЦикла;
Этот пример иллюстрирует правильный подход к работе с датами в запросах: всегда используйте параметры и обрезайте время, если оно не нужно.
FAQ: Частые вопросы о датах в 1С
Как в 1С получить первый день года?
Используйте функцию НачалоГода():
ПервыйДеньГода = НачалоГода(ТекущаяДата());
// Или для конкретного года:
ПервыйДень2026 = Дата(2026, 1, 1);
Почему при сравнении дат условие не срабатывает?
Скорее всего, вы сравниваете даты с учётом времени. Обрежьте время функцией НачалоДня():
Если НачалоДня(Документ.Дата) = НачалоДня(ТекущаяДата()) Тогда
Также проверьте, не является ли одна из дат пустой (Дата(1,1,1) — минимальная возможная дата в 1С).
Как в 1С прибавить к дате 3 месяца?
Используйте функцию ДобавитьМесяц():
НоваяДата = ДобавитьМесяц(ТекущаяДата(), 3);
Обратите внимание, что при добавлении месяцев к последнему дню месяца (например, 31 января + 1 месяц) результат может отличаться от ожидаемого (будет 28 февраля или 31 марта, в зависимости от года).
Как вычесть из одной даты другую, чтобы получить разницу в днях?
Просто вычтите одну дату из другой — результат будет в днях (дробная часть — время):
РазницаВДнях = КонечнаяДата - НачальнаяДата;
// Например:
Разница = Дата(2026, 5, 20) - Дата(2026, 5, 15); // Вернёт 5
Как в 1С получить текущую дату без времени?
Используйте комбинацию НачалоДня(ТекущаяДата()):
ДатаБезВремени = НачалоДня(ТекущаяДата());
Это обрежет часы, минуты и секунды, оставив только календарную дату.