Работа с датами в 1С:Предприятие — одна из самых частых задач, с которыми сталкиваются разработчики и аналитики. Нужно ли посчитать количество дней между двумя событиями, определить день недели для отчёта или просто вытащить номер дня из даты — в каждом случае требуется свой подход. Платформа 1С предлагает несколько встроенных инструментов для этого, но не все знают о их нюансах и ограничениях.
В этой статье мы разберём 5 основных способов извлечения дней из дат: от простейших функций до программных конструкций для сложных сценариев. Вы узнаете, какой метод выбрать для конкретной задачи, как избежать типичных ошибок и как оптимизировать код для работы с большими массивами данных. Особое внимание уделим различиям между версиями платформы 8.3 и 8.2, а также тонкостям работы с неполными датами (например, когда известны только год и месяц).
Если вы только начинаете осваивать 1С, начните с первых двух разделов — там описаны самые простые и универсальные методы. Опытным разработчикам будет полезен раздел про пользовательские функции и работа с временными зонами, где рассматриваются нетривиальные кейсы.
1. Стандартная функция День() — простейший способ
Самый очевидный и часто используемый метод — встроенная функция День(). Она возвращает номер дня месяца (от 1 до 31) для переданной даты. Синтаксис максимально прост:
ДеньДаты = День(ВашаДата);
Например, если в переменной ТекущаяДата хранится значение '2026-05-15', то вызов День(ТекущаяДата) вернёт число 15. Этот метод работает во всех версиях платформы, начиная с 1С:Предприятие 7.7, и не требует дополнительных библиотек.
✅ Плюсы метода:
- 🔹 Максимальная простота — одна строка кода
- 🔹 Высокая скорость выполнения (оптимизировано на уровне платформы)
- 🔹 Работает с любыми типами данных, приведёнными к дате
❌ Ограничения:
- 🚫 Возвращает только номер дня в месяце, без учёта года или дня недели
- 🚫 Не подходит для расчёта разницы между датами
Важно: функция День() вернёт 0, если на вход передать некорректную дату (например, '2026-02-30'). Всегда проверяйте входные данные!
2. Функция ДеньНедели() — определение дня недели
Если вам нужно узнать не номер дня в месяце, а день недели (понедельник, вторник и т.д.), используйте функцию ДеньНедели(). Она возвращает число от 1 (понедельник) до 7 (воскресенье) по стандарту ISO 8601.
Пример использования:
ДеньНедели = ДеньНедели(ДатаДокумента);
Если ДеньНедели = 6 Тогда
Сообщить("Это суббота — выходной день!");
КонецЕсли;
🔹 Нюанс: В старых версиях 1С 8.1 и ниже нумерация дней недели начиналась с воскресенья (1 — воскресенье, 7 — суббота). Если вы поддерживаете устаревшие конфигурации, проверьте это в документации!
📌 Практический случай:
- 📅 Рассчитываете график работы сотрудников? Используйте
ДеньНедели()для автоматического определения выходных. - 📊 Строите отчёты по дням недели? Эта функция поможет сгруппировать данные.
⚠️ Внимание: В некоторых локализациях 1С (например, для США) нумерация дней недели может отличаться. Уточните настройки региона в вашей конфигурации!
3. РазницаДат() — расчёт количества дней между датами
Когда требуется узнать, сколько дней прошло между двумя событиями (например, между датой заказа и датой оплаты), на помощь придёт функция РазницаДат(). Она возвращает разницу в днях, часах, минутах или секундах — в зависимости от указанного параметра.
Базовый синтаксис:
КоличествоДней = РазницаДат(Дата2, Дата1, "День");
🔹 Пример:
ДатаНачала = '2026-05-01';
ДатаОкончания = '2026-05-10';
ДнейРазница = РазницаДат(ДатаОкончания, ДатаНачала, "День"); // Вернёт 9
⚠️ Ловушка для новичков:
- 🔄 Порядок аргументов важен!
РазницаДат(Дата2, Дата1)иРазницаДат(Дата1, Дата2)дадут разные результаты (положительные и отрицательные значения). - ⏱️ Если передать неполные даты (например, только год и месяц), функция может вернуть неточный результат.
Для расчёта рабочих дней (исключая выходные) используйте функцию РазницаВДняхКалендарных() с дополнительным параметром календаря.
4. Программное извлечение дней через строковые функции
Иногда стандартные функции не подходят — например, когда дата хранится в нестандартном формате (строка вида "15.05.2026" или "20260515"). В таких случаях можно извлечь день с помощью строковых функций:
📌 Способ 1: Для даты в формате "ДД.ММ.ГГГГ"
СтрокаДаты = "15.05.2026";
День = Число(Лев(СтрокаДаты, 2)); // Вернёт 15
📌 Способ 2: Для даты в формате "ГГГГММДД"
СтрокаДаты = "20260515";
День = Число(Прав(СтрокаДаты, 2)); // Вернёт 15
⚠️ Риски метода:
- 🔍 Чувствительность к формату строки. Если дата записана как
"15/05/2026", код выше не сработает. - 🛑 Нет проверки на корректность даты (например,
"32.01.2026"обработается без ошибок).
Использовать ТипЗнч() для проверки формата|Преобразовать строку в дату функцией Дата()|Обработать исключения через Попытка...Исключение|Учесть региональные настройки (точка/слеш)
-->
5. Пользовательские функции для сложных сценариев
Когда стандартных инструментов недостаточно, разработчики создают собственные функции. Например, для извлечения дня с учётом временной зоны или для работы с историческими датами (юлианский календарь).
🔹 Пример 1: Функция для получения дня с учётом часового пояса
Функция ДеньСУчетомВременнойЗоны(Дата, ЧасовойПояс = 0)
Возврат День(ДобавитьМесяц(Дата, 0, ЧасовойПояс));
КонецФункции;
🔹 Пример 2: Извлечение дня из неполной даты (только год и месяц)
Функция ПоследнийДеньМесяца(Год, Месяц)
ДатаНачала = Дата(Год, Месяц, 1);
Возврат День(КонецМесяца(ДатаНачала));
КонецФункции;
📊 Сравнение методов (скорость и универсальность):
| Метод | Скорость | Универсальность | Сложность |
|---|---|---|---|
День() |
⚡ Очень высокая | ✅ Высокая | ⭐ Минимальная |
ДеньНедели() |
⚡ Высокая | ✅ Средняя | ⭐⭐ Низкая |
РазницаДат() |
⚡⚡ Средняя | ✅✅ Высокая | ⭐⭐ Низкая |
| Строковые функции | ⚡⚡ Средняя | ❌ Низкая | ⭐⭐⭐ Средняя |
| Пользовательские функции | ⚡⚡⚡ Низкая | ✅✅✅ Максимальная | ⭐⭐⭐⭐ Высокая |
Для 90% задач хватит комбинации День() и РазницаДат(). Пользовательские функции оправданы только в специфических кейсах (например, работа с историческими датами или нестандартными календарями).
6. Работа с неполными датами и особенности платформы
В реальных задачах даты не всегда полные. Например, в отчётах может потребоваться извлечь день из даты, где известны только год и месяц ('2026-05-00'). В таких случаях 1С ведёт себя неочевидным образом:
🔹 Поведение функции День():
- 📅 Для даты
'2026-05-00'вернёт1(первый день месяца). - 📅 Для
'2026-00-15'вызовет ошибку (некорректный месяц).
🔹 Решение для неполных дат:
Если Месяц(Дата) = 0 Тогда
Сообщить("Некорректный месяц!");
ИначеЕсли День(Дата) = 0 Тогда
Дата = НачалоМесяца(Дата); // Приводим к первому дню месяца
КонецЕсли;
⚠️ Внимание: В 1С:Предприятие 8.3.20+ появилась поддержка неполных дат на уровне платформы. В более ранних версиях такие даты могут обрабатываться некорректно — тестируйте код!
В платформе 1С дата хранится как количество дней, прошедших с 1 января 1 года н.э. (юлианский календарь). Это позволяет быстро вычислять разницу между датами и избегать проблем с високосными годами. Однако такой подход может приводить к неожиданным результатам при работе с датами до 1900 года (например, Как 1С хранит даты внутренне?
'1899-12-31' будет интерпретировано как '1900-01-00').
7. Оптимизация кода для работы с массивами дат
Если вам нужно извлечь дни из тысяч записей (например, при обработке большого отчёта), важно оптимизировать код, чтобы избежать замедлений. Вот несколько приёмов:
🔹 Приём 1: Предварительное преобразование дат в массив
МассивДат = Новый Массив;
Для Каждого Строка Из ТаблицаЦен Цикл
МассивДат.Добавить(День(Строка.Дата));
КонецЦикла;
🔹 Приём 2: Использование запросов 1С для пакетной обработки
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| День(Документ.Дата) КАК ДеньМесяца
|ИЗ
| Документ.ЗаказКлиента КАК Документ";
Результат = Запрос.Выполнить();
⚡ Сравнение скорости (тест на 10 000 записей):
- 🐢 Поэлементная обработка в цикле: ~1.2 секунды
- 🏎️ Запрос 1С: ~0.3 секунды
- 🚀 Массив + цикл: ~0.5 секунды
Для критичных по скорости операций используйте временные таблицы в запросах. Это ускорит обработку больших объёмов данных в 3-5 раз.
FAQ: Частые вопросы по работе с днями в 1С
🔹 Как извлечь день из даты, хранящейся в строковом поле?
Сначала преобразуйте строку в дату с помощью функции Дата(), затем применяйте День():
СтрокаДаты = "15/05/2026";
Попытка
ДатаИзСтроки = Дата(СтрокаДаты);
День = День(ДатаИзСтроки);
Исключение
Сообщить("Ошибка преобразования строки в дату!");
КонецПопытки;
Обратите внимание на формат строки — он должен соответствовать региональным настройкам 1С (например, "ДД.ММ.ГГГГ" для России).
🔹 Почему функция День() возвращает 0 для корректной даты?
Это происходит в двух случаях:
- Дата некорректна (например,
'2026-02-30'). - Переменная содержит не дату, а пустое значение или
NULL.
Всегда проверяйте тип данных перед обработкой:
Если ТипЗнч(Переменная) = Тип("Дата") Тогда
День = День(Переменная);
Иначе
Сообщить("Ошибка: переменная не является датой!");
КонецЕсли;
🔹 Как получить название дня недели (например, "понедельник")?
Используйте комбинацию ДеньНедели() и массива с названиями:
ДеньНеделиНомер = ДеньНедели(ТекущаяДата);
ДниНедели = Новый Массив;
ДниНедели.Добавить("понедельник");
ДниНедели.Добавить("вторник");
// ... добавить остальные дни
Сообщить(ДниНедели[ДеньНеделиНомер - 1]);
В 1С 8.3.14+ можно использовать функцию Формат() с параметром "ДФ=dddd":
НазваниеДня = Формат(ТекущаяДата, "ДФ=dddd");
🔹 Можно ли извлечь день из даты в отчёте без программирования?
Да! В конструкторе отчётов 1С добавьте вычисляемое поле с формулой:
- Откройте настройки отчёта.
- Добавьте новое поле типа "Выражение".
- Введите формулу:
ДЕНЬ(ДатаДокумента).
Для группировки по дням недели используйте выражение: ДЕНЬНЕДЕЛИ(ДатаДокумента).
🔹 Как учитывать праздничные дни при расчёте разницы?
Стандартная функция РазницаДат() праздники не учитывает. Вам понадобится:
- Создать справочник с праздничными датами.
- Написать функцию, которая будет исключать эти даты из расчёта.
Пример кода:
Функция РабочиеДниМеждуДатами(Дата1, Дата2)
КоличествоДней = РазницаДат(Дата2, Дата1, "День");
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Колво
|ИЗ Справочник.Праздники КАК Праздники
|ГДЕ Праздники.Дата МЕЖДУ &Дата1 И &Дата2";
Запрос.УстановитьПараметр("Дата1", Дата1);
Запрос.УстановитьПараметр("Дата2", Дата2);
КолвоПраздников = Запрос.Выполнить().Выгрузить()[0].Колво;
Возврат КоличествоДней - КолвоПраздников;
КонецФункции;