Работа с датами и временем в 1С:Предприятие 8.3 — одна из самых востребованных задач при разработке конфигураций, отчетов и обработок. Казалось бы, что может быть проще, чем прибавить к дате несколько дней или часов? Однако на практике программисты сталкиваются с нюансами: учет рабочих/выходных дней, переход на летнее/зимнее время, разные форматы хранения данных. Ошибки здесь чреваты сбоями в расчетах зарплаты, логистике или финансовых операциях.
Эта статья поможет разобраться, как корректно складывать даты и время в 1С с учетом всех особенностей платформы. Мы рассмотрим базовые функции, типовые ошибки и продвинутые сценарии — от простого сложения дней до работы с временными зонами. Особое внимание уделим практическим примерам кода, которые можно сразу использовать в своих конфигурациях.
Если вы только начинаете осваивать 1С, не пугайтесь: большинство операций интуитивно понятны. Опытным разработчикам будут полезны разделы про оптимизацию кода и обход "подводных камней". А для тех, кто работает с международными проектами, мы затрагиваем вопросы локализации форматов даты.
1. Базовые функции для работы с датами в 1С
Платформа 1С:Предприятие предоставляет встроенный тип данных Дата, который автоматически обрабатывает календарные правила. Основные функции для манипуляции датами:
- 📅 ДатаВремя() — создает значение типа Дата с указанием года, месяца, дня, часов, минут, секунд. Пример:
ДатаВремя(2026, 5, 15, 14, 30, 0). - ⏳ ДобавитьМесяц(), ДобавитьДень(), ДобавитьЧас() — увеличивают дату на заданный интервал. Важно: эти функции корректно обрабатывают переходы между месяцами.
- 🔄 НачалоДня(), КонецДня() — возвращают дату с временем 00:00:00 или 23:59:59 соответственно.
- ⏱️ ТекущаяДата() — возвращает текущие дату и время сервера 1С.
Простейшее сложение дней выглядит так:
ДатаОтгрузки = ДатаВремя(2026, 5, 20);
ДатаОтгрузки = ДобавитьДень(ДатаОтгрузки, 5); // Прибавляем 5 дней
Обратите внимание: функция ДобавитьДень() автоматически учитывает количество дней в месяце. Например, если к 31.01.2026 прибавить 1 день, результат будет 01.02.2026, а не 32.01.2026.
Для быстрого получения даты "сегодня без времени" используйте конструкцию НачалоДня(ТекущаяДата()). Это избавит от проблем с сравнением дат, где время может отличаться на доли секунды.
2. Сложение времени: часы, минуты, секунды
Для операций со временем в 1С используются те же принципы, что и для дат, но с другими функциями. Основные инструменты:
- ⏰ ДобавитьЧас() — прибавляет указанное количество часов. Пример:
ДобавитьЧас(ВремяНачала, 2). - ⏲️ ДобавитьМинуту()/ДобавитьСекунду() — аналогично для минут и секунд.
- 🔢 Час(), Минута(), Секунда() — извлекают соответствующие компоненты из значения типа Дата.
Пример сложения времени с учетом перехода через полночь:
ВремяОкончания = ДатаВремя(2026, 5, 15, 22, 0, 0); // 22:00
ВремяОкончания = ДобавитьЧас(ВремяОкончания, 3); // Результат: 01:00 следующего дня
Важный нюанс: при сложении времени 1С автоматически корректирует дату, если время выходит за пределы суток. Это избавляет от ручной обработки случаев вроде "23:00 + 2 часа = 01:00 следующего дня".
⚠️ Внимание: При работе с временными зонами функции сложения времени не учитывают переход на летнее/зимнее время. Для таких случаев требуется дополнительная логика или использование внешних библиотек.
3. Продвинутые сценарии: рабочие дни, праздники, календари
В бизнес-задачах часто требуется прибавлять только рабочие дни, исключая выходные и праздники. В 1С для этого есть несколько подходов:
1. Использование объекта "Календарь":
Календарь = Календари.ПроизводственныйКалендарь();
ДатаДоставки = Календарь.ДобавитьРабочиеДни(ДатаОтгрузки, 3); // Прибавляем 3 рабочих дня
2. Ручная проверка (если календарь не настроен):
Функция ДобавитьРабочиеДни(ДатаНачала, КоличествоДней)
ТекущаяДата = ДатаНачала;
ОсталосьДней = КоличествоДней;
Пока ОсталосьДней > 0 Цикл
ТекущаяДата = ДобавитьДень(ТекущаяДата, 1);
Если НЕ ТекущаяДата.ДеньНедели() = 6 И НЕ ТекущаяДата.ДеньНедели() = 7 Тогда
ОсталосьДней = ОсталосьДней - 1;
КонецЕсли;
КонецЦикла;
Возврат ТекущаяДата;
КонецФункции
Для учета праздничных дней потребуется создать справочник с датами праздников и модифицировать функцию соответствующей проверкой.
Если ваша компания работает в нескольких регионах с разными праздничными днями, создайте справочник "РегиональныеПраздники" с полями "Регион" и "Дата". В функции добавьте проверку:
Продолжить; // Пропускаем праздничный день КонецЕсли;Как учитывать региональные праздники?
Если НЕ ПустаяСсылка(РегиональныеПраздники.НайтиПоРеквизиту("Дата", ТекущаяДата)) Тогда
| Метод | Преимущества | Недостатки |
|---|---|---|
| Календарь 1С | Автоматический учет выходных и праздников | Требует предварительную настройку календаря |
| Ручная функция | Гибкость, возможность кастомизации | Требует поддержки кода при изменении правил |
| Внешняя библиотека | Поддержка сложных сценариев (например, мусульманский календарь) | Дополнительные зависимости в проекте |
4. Ошибки и "подводные камни" при работе с датами
Даже опытные разработчики 1С иногда сталкиваются с неожиданными результатами при операциях с датами. Рассмотрим типовые ошибки:
- 🗓️ Неучет временной зоны: Функция
ТекущаяДата()возвращает время сервера, которое может отличаться от локального времени пользователя. Для клиент-серверных решений это критично. - ⏳ Переполнение даты: Прибавление большого количества дней (например, 10000) может привести к ошибке переполнения.
- 🔄 Неявное приведение типов: Сравнение даты с строкой (например,
Если Дата = "20.05.2026" Тогда) работает, но может давать неожиданные результаты. - 📊 Форматирование при выводе: Дата в формате
ДД.ММ.ГГГГможет быть интерпретирована по-разному в различных локалях (например, в США сначала идет месяц).
Пример ошибочного кода с неявным приведением:
ДатаСтрока = "31.02.2026"; // Несуществующая дата
Дата = ДатаСтрока; // 1С автоматически преобразует в 03.03.2026!
⚠️ Внимание: При обмене данными с внешними системами всегда явным образом указывайте формат даты. Например, для JSON используйте стандартISO 8601(YYYY-MM-DDTHH:MM:SS). В 1С для этого есть функцияФормат(Дата, "ДФ=yyyy-MM-dd; ЧФ=ЧЦ=0").
Используются ли явные приведения типов?|Учтена ли временная зона сервера?|Проверены ли граничные значения (например, конец месяца)?|Тестировался ли код на разных конфигурациях локали?|Документированы ли неочевидные моменты?
-->
5. Оптимизация производительности при массовых операциях
Если вам нужно обработать тысячи дат (например, при построении графика или расчете просрочек), важно оптимизировать код. Вот несколько рекомендаций:
1. Избегайте циклов там, где можно использовать массовые операции. Например, для сдвига дат в выборке лучше использовать временную таблицу с предварительно рассчитанными значениями.
2. Кэшируйте результаты часто используемых функций. Например, если вам многократно нужно проверять, является ли день рабочим, загрузите данные календаря в массив один раз.
3. Используйте серверные процедуры для тяжелых вычислений. Клиентский код в 1С работает медленнее, особенно при большом объеме данных.
Пример оптимизированного кода для массового сдвига дат:
// Серверная функция
Функция СдвинутьДатыМассово(МассивДат, КоличествоДней)
Результат = Новый Массив();
Для Каждого Дата Из МассивДат Цикл
Результат.Добавить(ДобавитьДень(Дата, КоличествоДней));
КонецЦикла;
Возврат Результат;
КонецФункции
При массовой обработке более 10 000 дат рассмотрите возможность использования механизма распределенных задач (BackgroundJobs в 1С:Предприятие 8.3.20+), чтобы не блокировать интерфейс пользователя.
6. Работа с временными зонами и летним временем
Если ваша система работает в нескольких часовых поясах или интегрируется с международными сервисами, придется учитывать временные зоны. В 1С для этого есть несколько подходов:
1. Хранение времени в UTC с последующим преобразованием:
// Преобразование локального времени в UTC
UTCВремя = ДатаВремя(2026, 5, 15, 14, 0, 0).ВУТС();
// Обратно в локальное время
ЛокальноеВремя = UTCВремя.ИзУТС();
2. Ручная корректировка с учетом смещения:
СмещениеМск = 3; // Часовой пояс Москвы (UTC+3)
ЛокальноеВремя = ДобавитьЧас(UTCВремя, СмещениеМск);
Для учета перехода на летнее/зимнее время потребуется таблица правил или интеграция с внешним сервисом (например, Time Zone Database). В стандартной поставке 1С таких инструментов нет.
⚠️ Внимание: При работе с историческими данными учитывайте, что правила перехода на летнее/зимнее время менялись. Например, в России с 2014 года отменен переход на зимнее время, но в других странах правила могут отличаться.
Для международных проектов всегда храните время в UTC, а преобразование в локальное время выполняйте только при выводе данных пользователю. Это избавит от проблем с расхождениями во временных зонах.
7. Интеграция с внешними системами: JSON, XML, SQL
При обмене данными с другими системами формат даты становится критически важным. Рассмотрим типовые сценарии:
1. JSON:
Стандарт де-факто — ISO 8601. В 1С для преобразования используйте:
ДатаJSON = Формат(Дата, "ДФ=yyyy-MM-dd; ЧФ=ЧЦ=0; ДЛФ=Т; ЧН=:"); // "2026-05-15T14:30:00"
2. XML:
Часто используется формат с явным указанием часового пояса:
ДатаXML = Формат(Дата, "ДФ=yyyy-MM-dd; ЧФ=ЧЦ=0; ДЛФ=Т; ЧН=; ТЧ=zzz");
// "2026-05-15T14:30:00+03:00"
3. SQL:
Для запросов к базам данных (например, PostgreSQL или MS SQL) используйте параметризованные запросы с явным указанием типа:
Запрос = Новый Запрос();
Запрос.Текст = "ВЫБРАТЬ * ИЗ Документы ГДЕ Дата > &Дата";
Запрос.УстановитьПараметр("Дата", ДатаНачала);
При чтении данных из внешних источников всегда валидируйте формат даты перед преобразованием в тип 1С. Например:
Попытка
Дата = Дата(СтрокаДатаИзJSON);
Исключение
Сообщить("Ошибка формата даты: " + ОписаниеОшибки());
КонецПопытки;
Часто задаваемые вопросы
Как прибавить к дате 1 месяц с учетом конца месяца?
Используйте функцию ДобавитьМесяц(). Она автоматически корректирует дату на последний день месяца, если исходная дата была концом месяца. Например:
Дата = ДатаВремя(2026, 1, 31);
НоваяДата = ДобавитьМесяц(Дата, 1); // Результат: 29.02.2026 (а не 31.02!)
Если нужно всегда получать тот же номер дня (даже если его не существует в целевом месяце), используйте ДобавитьДень(ДобавитьМесяц(Дата, 1), День(Дата) - День(НачалоМесяца(ДобавитьМесяц(Дата, 1)))).
Почему при сложении даты и времени получаю неверный результат?
Наиболее вероятные причины:
- Вы работаете с датой в формате строки, а не типа
Дата. Всегда используйте явное преобразование:Дата = Дата(СтрокаДата). - Не учтена временная зона сервера. Проверьте настройки кластера 1С.
- Переполнение значения. Максимальная дата в 1С —
31.12.9999 23:59:59.
Для диагностики выведите промежуточные значения с помощью Сообщить().
Как вычесть одну дату из другой, чтобы получить разницу в днях?
Используйте функцию РазницаДней():
ДниРазницы = РазницаДней(Дата2, Дата1);
Для часов, минут или секунд есть аналогичные функции: РазницаЧасов(), РазницаМинут().
Если нужна разница в рабочих днях, используйте метод РазницаРабочихДней() объекта Календарь.
Можно ли в 1С работать с миллисекундами?
Тип Дата в 1С не поддерживает миллисекунды. Если требуется высокая точность (например, для логов или интеграции с внешними системами), храните миллисекунды отдельно в числовом поле и комбинируйте при выводе:
ДатаСМиллисекундами = Формат(Дата, "ДФ=yyyy-MM-dd; ЧФ=ЧЦ=0; ЧМС=мс") + "." + Миллисекунды;
Как учитывать праздничные дни в разных странах?
Для международных проектов:
- Создайте справочник "ГлобальныеПраздники" с полями "Страна", "Регион", "Дата", "Повторяющийся".
- Реализуйте функцию проверки с учетом страны пользователя (можно брать из справочника "Пользователи").
- Для динамического обновления праздников интегрируйтесь с API типа Google Calendar или Nager.Date.
Пример структуры справочника:
Праздник = Справочники.ГлобальныеПраздники.СоздатьЭлемент();
Праздник.Страна = Справочники.Страны.НайтиПоНаименованию("Германия");
Праздник.Дата = ДатаВремя(2026, 12, 25); // Рождество
Праздник.Повторяющийся = Истина;