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

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

В этой статье мы рассмотрим:

  • 📅 Базовый синтаксис создания значений типа ДатаВремя в коде
  • ⏳ Функции преобразования между строками, числами и датами
  • ⚠️ Типичные ошибки и как их избежать (включая проблемы с локализацией)
  • 🔄 Работа с интервалами и временными зонами
  • 📊 Оптимизация кода при массовой обработке дат
📊 Как часто вы работаете с типом"ДатаВремя" в 1С?
Ежедневно
Несколько раз в неделю
Редко, только в специфических задачах
Никогда не использовал

1. Создание значения типа ДатаВремя: синтаксис и варианты

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

Самый простой способ — использование конструктора Дата:

ТекущаяДата = Дата; // Текущие дата и время с точностью до секунды

ТолькоДата = Дата(2023, 12, 31); // 31 декабря 2023 года, время 00:00:00

ДатаСоВременем = Дата(2023, 12, 31, 14, 30, 0); // 31.12.2023 14:30:00

Особенности конструктора:

  • 🔹 Если не указаны часы/минуты/секунды, они автоматически устанавливаются в 00:00:00
  • 🔹 Год можно указывать в формате YYYY (например, 2023) или YY (например, 23 — будет интерпретировано как 2023)
  • 🔹 Месяц и день не могут выходить за пределы допустимых значений (иначе возникнет ошибка)

Для создания"пустой" даты (которая часто используется как признак отсутствия значения) применяется специальная функция:

ПустаяДата = Дата(1, 1, 1); // 01.01.0001 00:00:00
💡

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

2. Преобразование строк в ДатаВремя и обратно

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

Базовый синтаксис:

ДатаИзСтроки = ДатаЗнач("31.12.2023 14:30:00");

Ключевые моменты:

  • 📌 Формат строки должен соответствовать региональным настройкам базы. Например, в русской локали ожидается формат ДД.ММ.ГГГГ, а в американской — ММ/ДД/ГГГГ
  • 📌 Если строка содержит только дату без времени, часы/минуты/секунды будут установлены в 00:00:00
  • 📌 При некорректном формате возникнет исключение Ошибка при вызове метода контекста (ДатаЗнач)

Для обратного преобразования (из ДатаВремя в строку) используется функция Формат:

СтрокаДаты = Формат(ТекущаяДата,"ДФ=dd.MM.yyyy HH:mm:ss");

СтрокаДатыБезВремени = Формат(ТекущаяДата,"ДЛФ=D"); //"31 декабря 2023 г."

ФорматПример выводаОписание
ДФ=dd.MM.yyyy31.12.2023Краткий формат даты
ДЛФ=D31 декабря 2023 г.Длинный формат даты
ДФ=dd.MM.yyyy HH:mm:ss31.12.2023 14:30:00Дата и время
ВФ=HH:mm14:30Только время
💡

Всегда проверяйте региональные настройки базы перед парсингом строковых дат. В многопользовательских системах формат может отличаться от ожидаемого!

3. Работа с интервалами и арифметика дат

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

Основные операции:

  • 🔢 Сложение/вычитание секунд: Дата1 + 3600 (добавит 1 час)
  • 📅 Сложение/вычитание дней: Дата1 + 7 (добавит 7 дней)
  • 🔄 Разность дат: Дата2 - Дата1 (вернёт количество секунд между датами)

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

НоваяДата = ДобавитьМесяц(ТекущаяДата, 3); // +3 месяца

НоваяДата = КонецМесяца(ТекущаяДата); // Последний день текущего месяца

НоваяДата = НачалоГода(ТекущаяДата); // 01.01.ГГГГ 00:00:00

Пример расчёта количества полных дней между двумя датами:

КоличествоДней = Цел((Дата2 - Дата1) / 86400); // 86400 секунд в сутках
Что будет если вычесть из даты число?

Если из значения типа ДатаВремя вычесть число (например, Дата1 - 5), платформа интерпретирует это как вычитание секунд, а не дней! Для вычитания дней используйте Дата1 - 5*86400 или функцию ДобавитьДень

4. Типичные ошибки и их решения

Даже опытные разработчики иногда сталкиваются с неочевидными ошибками при работе с датами. Вот наиболее распространённые проблемы и способы их избежать:

⚠️ Внимание: При сравнении дат без учёта времени (Дата1 = Дата2) платформа сравнивает полные значения включая секунды. Используйте НачалоДня для корректного сравнения календарных дат.

Частые ошибки:

  • 🚫 Неучёт временных зон: При обмене данными между системами в разных часовых поясах даты могут сдвигаться. Всегда уточняйте, в каком поясе хранятся данные.
  • 🚫 Парсинг строк без проверки: Функция ДатаЗнач вызывает исключение при некорректном формате. Используйте Попытка...Исключение:
Попытка

ДатаИзСтроки = ДатаЗнач(НепровереннаяСтрока);

Исключение

Сообщить("Ошибка формата даты:" + ОписаниеОшибки);

КонецПопытки;

  • 🚫 Игнорирование летнего времени: В некоторых регионах переход на летнее/зимнее время может сдвинуть время на час. Для критичных систем используйте UTC.

Пример корректного сравнения дат без учёта времени:

Если НачалоДня(Дата1) = НачалоДня(Дата2) Тогда

// Даты совпадают (без учёта времени)

КонецЕсли;

5. Работа с временными зонами и UTC

В современных распределённых системах учёт временных зон становится критически важным. Платформа 1С:Предприятие поддерживает работу с UTC (Всемирное координированное время) и локальным временем, но требует явного указания зоны при необходимости.

Основные функции для работы с UTC:

  • 🌍 ТекущаяУниверсальнаяДата — возвращает текущую дату/время в UTC
  • ЛокальнаяДатаВUTC — преобразует локальное время в UTC
  • 🔙 UTCВЛокальнуюДата — обратное преобразование

Пример синхронизации времени с внешним сервисом:

// Получаем время из внешнего API в UTC

ВнешнееВремяUTC = ДатаЗнач("2023-12-31T14:30:00Z");

// Преобразуем в локальное время текущей базы

ЛокальноеВремя = UTCВЛокальнуюДата(ВнешнееВремяUTC);

⚠️ Внимание: Настройки временной зоны базы данных могут отличаться от настроек операционной системы сервера. Всегда проверяйте актуальную зону через ТекущаяДатаВремя.ЧасовойПояс.

6. Оптимизация кода при массовой обработке дат

При работе с большими объёмами данных (например, при анализе истории документов за несколько лет) неэффективная обработка дат может значительно замедлить выполнение кода. Вот несколько приёмов для оптимизации:

Советы по оптимизации:

  • Избегайте повторных преобразований: Если дата уже в формате ДатаВремя, не конвертируйте её в строку и обратно без необходимости.
  • Используйте индексы: При выборках из базы по датам убедитесь, что соответствующие поля проиндексированы.
  • Кэшируйте часто используемые даты:
НачалоМесяца = НачалоМесяца(ТекущаяДата); // Вычисляем один раз

КонецМесяца = КонецМесяца(ТекущаяДата); // и используем многократно

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Документ.Ссылка КАК Ссылка

|ИЗ

| Документ.ЗаказПокупателя КАК Документ

|ГДЕ

| Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоМесяца));

Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецМесяца));

Используются ли индексы для полей с датами в базе?|Есть ли повторяющиеся вычисления одних и тех же дат?|Преобразуются ли даты в строки без необходимости?|Учитываются ли временные зоны при обмене данными?-->

7. Продвинутые приёмы: парсинг нестандартных форматов

Иногда даты поступают в нестандартных форматах, которые не распознаются функцией ДатаЗнач. В таких случаях приходится писать собственные алгоритмы парсинга. Рассмотрим пример разбора даты в формате ISO 8601 (например, "2023-12-31T14:30:00+03:00"):

Функция РазобратьISOДата(СтрокаДата)

// Упрощённый парсер для формата YYYY-MM-DDThh:mm:ss±hh:mm

ЧастиДаты = СтроковыеФункции.РазделитьСтроку(СтрокаДата,"T");

ДатаЧасть = ЧастиДаты[0];

ВремяЧасть = ЧастиДаты[1];

Год = Число(Лев(ДатаЧасть, 4));

Месяц = Число(Сред(ДатаЧасть, 6, 2));

День = Число(Сред(ДатаЧасть, 9, 2));

ВремяБезЗоны = Лев(ВремяЧасть, 8); //"hh:mm:ss"

Часы = Число(Лев(ВремяБезЗоны, 2));

Минуты = Число(Сред(ВремяБезЗоны, 4, 2));

Секунды = Число(Сред(ВремяБезЗоны, 7, 2));

Возврат Дата(Год, Месяц, День, Часы, Минуты, Секунды);

КонецФункции

Важно: При парсинге дат с указанием временной зоны (например, +03:00) необходимо дополнительно скорректировать результат с учётом смещения относительно UTC.

Для сложных случаев рекомендуется:

  • 🛠 Использовать регулярные выражения для извлечения компонентов даты
  • 📋 Создавать таблицу соответствия месяцев на разных языках (например,"January" = 1)
  • ⚠️ Всегда валидировать результат (например, проверять, что месяц находится в диапазоне 1-12)

FAQ: Частые вопросы по работе с ДатаВремя в 1С

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

Используйте функцию ТекущаяДата без параметров или обрежьте время с помощью НачалоДня:

ДатаБезВремени = НачалоДня(ТекущаяДата);

Это вернёт текущую дату с временем 00:00:00.

Почему при сравнении двух дат с одинаковым значением получаю Ложь?

Скорее всего, сравниваются даты с разным временем. Например, Дата(2023,12,31) (00:00:00) и Дата(2023,12,31,12,0,0) (12:00:00) не равны. Используйте НачалоДня для сравнения только календарных дат.

Как в 1С добавить к дате 1 месяц, чтобы корректно обрабатывался переход через год?

Используйте функцию ДобавитьМесяц — она автоматически корректирует год при переходе:

НоваяДата = ДобавитьМесяц(Дата(2023, 12, 31), 1); // Вернёт 31.01.2026

Эта функция учитывает количество дней в месяце (например, 31 декабря + 1 месяц = 31 января, а не 31 февраля).

Можно ли в 1С хранить дату без привязки к временной зоне?

Да, для этого используйте UTC. Функции ТекущаяУниверсальнаяДата и ЛокальнаяДатаВUTC позволяют работать с временем без привязки к локальному поясу. Это особенно важно для распределённых систем.

Как вычислить количество рабочих дней между двумя датами?

В стандартной поставке нет встроенной функции для этого, но можно написать собственную процедуру:

Функция РабочиеДни(ДатаНачало, ДатаКонец)

Дни = 0;

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

Пока ТекущаяДата <= КонецДня(ДатаКонец) Цикл

Если НЕ ТекущаяДата.ДеньНедели = 6 И НЕ ТекущаяДата.ДеньНедели = 7 Тогда

Дни = Дни + 1;

КонецЕсли;

ТекущаяДата = ТекущаяДата + 86400; // +1 день

КонецЦикла;

Возврат Дни;

КонецФункции

Для учёта праздников потребуется дополнительно проверять даты по календарю.