Определение количества дней в месяце — одна из самых распространённых задач при работе с датами в 1С:Предприятие. Казалось бы, что может быть проще? Но на практике программисты сталкиваются с нюансами: високосные годы, разная длительность месяцев, необходимость учитывать рабочие/выходные дни. В этой статье мы разберём 7 способов получить количество дней в месяце — от стандартных функций платформы до универсальных алгоритмов, работающих даже с историческими датами.

Вы узнаете, как:

  • 📅 Использовать встроенную функцию ДнейВМесяце() и её ограничения
  • 🔄 Получать количество дней для произвольной даты (включая будущие периоды)
  • 📊 Учитывать рабочие дни с помощью календарей
  • 💡 Оптимизировать код для массовой обработки дат

Все примеры приведены для актуальных версий 1С:Предприятие 8.3 и 8.2, но majority методов будут работать и в более ранних редакциях. Если вы часто работаете с датами в конфигурациях (например, при расчёте зарплаты, планировании графиков или аналитике), эта статья поможет избежать типичных ошибок и написать надёжный код.

📊 Как часто вам приходится работать с датами в 1С?
Ежедневно
Несколько раз в неделю
Редко
Никогда

1. Стандартная функция ДнейВМесяце() — простейший способ

Самый очевидный метод — использовать встроенную функцию ДнейВМесяце(). Она возвращает количество дней в указанном месяце с учётом високосных лет. Синтаксис:

КоличествоДней = ДнейВМесяце(Год, Месяц);

Где:

  • 📌 Год — числовое значение года (например, 2026)
  • 📌 Месяц — номер месяца от 1 (январь) до 12 (декабрь)

Пример использования:

Сообщить(ДнейВМесяце(2026, 2)); // Вернёт 29 (февраль 2026 — високосный год)

Преимущества метода:

  • ⚡ Максимальная простота — одна строка кода
  • 🔒 Надёжность — платформа сама учитывает високосные годы
  • 📈 Быстродействие — встроенная функция оптимизирована

Ограничения:

  • ❌ Требует явного указания года и месяца (нельзя передать дату типа Дата)
  • ❌ Не работает с датами до 1900 года (вернёт ошибку)
ТекущаяДата = ТекущаяДата();

КоличествоДней = ДнейВМесяце(Год(ТекущаяДата), Месяц(ТекущаяДата));

-->

2. Альтернатива: функция КонецМесяца() для работы с типом Дата

Если у вас уже есть переменная типа Дата, удобнее использовать функцию КонецМесяца(). Она возвращает последнюю дату месяца, после чего можно вычислить количество дней через День():

МояДата = '2026-02-15';

ПоследнийДень = КонецМесяца(МояДата);

КоличествоДней = День(ПоследнийДень); // 29 для февраля 2026

Когда этот метод удобнее ДнейВМесяце():

  • 🔄 Когда дата хранится в переменной типа Дата (не нужно извлекать год и месяц отдельно)
  • 📅 При работе с диапазонами дат (например, в отчётах)
  • 🔄 Когда требуется не только количество дней, но и последняя дата месяца

Пример для текущего месяца:

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

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

Что возвращает КонецМесяца() для февраля 2000 года?

Функция вернёт '2000-02-29', так как 2000 год был високосным (делится на 400 без остатка).

3. Универсальный алгоритм для любых дат (включая исторические)

Встроенные функции не работают с датами до 1900 года. Если вам нужно обработать исторические данные (например, в архивных отчётах), используйте самостоятельный расчёт с учётом правил високосных лет:

Функция ДнейВМесяцеУниверсально(Год, Месяц)

Если Месяц = 2 Тогда

// Проверка на високосный год

Если (Год % 4 = 0 И Год % 100 <> 0) Или (Год % 400 = 0) Тогда

Возврат 29;

Иначе

Возврат 28;

КонецЕсли;

ИначеЕсли Месяц В [4, 6, 9, 11] Тогда

Возврат 30;

Иначе

Возврат 31;

КонецЕсли;

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

Преимущества:

  • 🌍 Работает с любыми годами (включая до 1900 и после 2100)
  • 🔧 Не зависит от ограничений платформы
  • 📜 Подходит для исторических расчётов (например, в музеях или архивах)

Недостатки:

  • ⚠️ Требует ручного тестирования для краевых случаев
  • ⏱ Дольше выполняется, чем встроенные функции
💡

Для большинства бизнес-задач в 1С достаточно встроенных функций. Универсальный алгоритм нужен только при работе с нестандартными датами (до 1900 года или после 2100).

4. Получение рабочих дней в месяце (с учётом календарей)

Если вам нужно не общее количество дней, а количество рабочих дней (например, для расчёта зарплаты или планирования задач), используйте Календарь из подсистемы "Зарплата и Управление Персоналом".

Пример кода:

// Получаем календарь (например, "Пятидневка")

Календарь = Календари.Пятидневка;

// Устанавливаем период (первый и последний день месяца)

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

КонецМесяца = КонецМесяца(ТекущаяДата());

// Получаем количество рабочих дней

РабочиеДни = Календарь.РабочиеДни(НачалоМесяца, КонецМесяца);

Нюансы:

  • 📅 Требуется наличие подсистемы "Зарплата и Управление Персоналом" в конфигурации
  • 🔧 Календари настраиваются в справочнике Календари (например, "Пятидневка", "Шестидневка")
  • ⚠️ Учитываются праздничные дни согласно законодательству РФ

Если подсистемы нет, можно использовать внешние обработки или написать свой алгоритм с учётом выходных. Например, для пятидневки:

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

РабочиеДни = 0;

ТекущаяДата = ДатаНачала;

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

Если ДеньНедели(ТекущаяДата) <> 6 И ДеньНедели(ТекущаяДата) <> 7 Тогда

РабочиеДни = РабочиеДни + 1;

КонецЕсли;

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

КонецЦикла;

Возврат РабочиеДни;

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

Убедитесь, что в конфигурации есть подсистема "Зарплата и Управление Персоналом"|Проверьте настройки календаря (пятидневка/шестидневка)|Учитывайте региональные праздники (если нужны)|Тестируйте код на краевых датах (например, январь с новогодними каникулами)-->

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

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

Способ 1: Кэширование результатов

Перем мКэшДнейВМесяце;

// Функция с кэшированием

Функция ДнейВМесяцеКэшированно(Год, Месяц)

КлючКэша = Строка(Год) + "_" + Строка(Месяц);

Если НЕ мКэшДнейВМесяце.Свойство(КлючКэша) Тогда

мКэшДнейВМесяце[КлючКэша] = ДнейВМесяце(Год, Месяц);

КонецЕсли;

Возврат мКэшДнейВМесяце[КлючКэша];

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

Способ 2: Векторизация (для больших массивов)

// Пример для массива дат

МассивДат = Новый Массив;

МассивДат.Добавить('2026-01-01');

МассивДат.Добавить('2026-02-01');

// ...

Результаты = Новый Массив;

Для Каждого Дата Из МассивДат Цикл

ПоследнийДень = КонецМесяца(Дата);

Результаты.Добавить(День(ПоследнийДень));

КонецЦикла;

Способ 3: Использование запроса (для СУБД)

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

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

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

"ВЫБРАТЬ

| День(КОНЕЦМЕСЯЦА(&Дата)) КАК КоличествоДней

|ИЗ

| МойРегистр КАК Т";

Запрос.УстановитьПараметр("Дата", ТекущаяДата());

Результат = Запрос.Выполнить();

💡

При работе с тысячами дат кэширование ускоряет выполнение в 10–100 раз. Для миллионов записей оптимально использовать запросы к СУБД.

6. Типичные ошибки и как их избежать

Даже опытные программисты иногда допускают ошибки при работе с датами. Рассмотрим самые распространённые:

Ошибка Причина Как исправить
Неверное количество дней в феврале Не учтён високосный год Использовать ДнейВМесяце() или проверять Год % 4
Ошибка "Неверный аргумент" в ДнейВМесяце() Передан год < 1900 Использовать универсальный алгоритм (раздел 3)
Неправильный расчёт рабочих дней Не учтены праздники или региональные особенности Настроить календарь в ЗУП или добавить проверку праздников
Медленная работа при массовой обработке Отсутствует кэширование Добавить кэш (раздел 5) или использовать запросы

Дополнительные ловушки:

  • 🕒 Часовые пояса: Если работаете с датами в разных поясах, приводите их к одному перед расчётами.
  • 📅 Начало/конец месяца: Функции НачалоМесяца() и КонецМесяца() возвращают дату с временем 00:00:00 и 23:59:59 соответственно. Это может влиять на сравнения.
  • 🔄 Переход на летнее/зимнее время: В редких случаях может сдвигать даты (актуально для исторических данных до 2011 года в РФ).
  • 📌 31 декабря (переход на новый год)
  • 📌 28–29 февраля (високосный год)
  • 📌 1 января (праздники)
-->

7. Практические примеры использования

Рассмотрим реальные сценарии, где требуется определять количество дней в месяце:

Пример 1: Расчёт нормы рабочего времени в табеле

// Получаем количество рабочих дней в месяце

РабочиеДни = Календарь.РабочиеДни(НачалоМесяца(ДатаОтчёта), КонецМесяца(ДатаОтчёта));

// Норма часов = рабочие дни * 8 часов

НормаЧасов = РабочиеДни * 8;

Пример 2: Планирование графика платежей

// Последний день месяца для оплаты

ДатаОплаты = КонецМесяца(ТекущаяДата());

Если ДеньНедели(ДатаОплаты) = 6 Тогда // Если суббота

ДатаОплаты = ДатаОплаты - 1; // Переносим на пятницу

ИначеЕсли ДеньНедели(ДатаОплаты) = 7 Тогда // Если воскресенье

ДатаОплаты = ДатаОплаты - 2; // Переносим на пятницу

КонецЕсли;

Пример 3: Аналитика продаж по месяцам

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

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

"ВЫБРАТЬ

| Год(Документ.Дата) КАК Год,

| Месяц(Документ.Дата) КАК Месяц,

| День(КОНЕЦМЕСЯЦА(Документ.Дата)) КАК ДнейВМесяце,

| СУММА(Документ.Сумма) КАК ОбщаяСумма

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Документ

|ГРУППИРОВАТЬ ПО

| Год(Документ.Дата),

| Месяц(Документ.Дата)";

Результат = Запрос.Выполнить();

Пример 4: Валидация введённой даты

Функция ДатаКорректна(ДатаСтрока)

Попытка

Дата = Дата(ДатаСтрока);

// Проверяем, что день не превышает количество дней в месяце

Если День(Дата) > ДнейВМесяце(Год(Дата), Месяц(Дата)) Тогда

Возврат Ложь;

КонецЕсли;

Возврат Истина;

Исключение

Возврат Ложь;

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

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

Как проверить, что февраль 2026 года високосный?

Можно использовать простой проверочный код:

Год = 2026;

Если (Год % 4 = 0 И Год % 100 <> 0) Или (Год % 400 = 0) Тогда

Сообщить("Високосный!");

Иначе

Сообщить("Не високосный");

КонецЕсли;

Для 2026 года выведет "Високосный!".

FAQ: Ответы на частые вопросы

🔹 Почему функция ДнейВМесяце() не работает с годами до 1900?

Платформа 1С:Предприятие внутренне хранит даты в формате, который не поддерживает годы до 1900 (ограничение связано с реализацией календарных функций в ядре системы). Для исторических дат используйте универсальный алгоритм из раздела 3.

🔹 Как получить количество дней в месяце для даты в формате строки?

Сначала преобразуйте строку в тип Дата, затем используйте КонецМесяца():

ДатаСтрока = "15.05.2026";

Дата = Дата(ДатаСтрока);

КоличествоДней = День(КонецМесяца(Дата)); // 31 для мая

🔹 Можно ли получить количество дней в месяце без программирования (в пользовательском режиме)?

Да, в есть встроенные возможности:

  1. Откройте календарь (например, в поле ввода даты).
  2. Выберите нужный месяц — внизу отобразится количество дней.
  3. Или используйте отчёт "Календарь" в подсистеме "Зарплата и Кадры".

Однако для автоматизации (например, в отчётах) всё равно потребуется программный код.

🔹 Как учесть региональные праздники при расчёте рабочих дней?

В подсистеме "Зарплата и Управление Персоналом":

  1. Откройте справочник Календари.
  2. Выберите или создайте календарь (например, "Пятидневка").
  3. В разделе "Праздничные дни" добавьте региональные даты.
  4. Используйте этот календарь в функции РабочиеДни().

Если подсистемы нет, придётся вручную добавлять проверки в код (например, через массив праздничных дат).

🔹 Почему мой код возвращает 28 дней для февраля 2026 года?

Скорее всего, вы:

  • Используете универсальный алгоритм (раздел 3), но неверно реализовали проверку високосного года.
  • Или передаёте в ДнейВМесяце() не тот год (например, 2023 вместо 2026).

Проверьте:

Сообщить(ДнейВМесяце(2026, 2)); // Должно вернуть 29
Функция ПолучитьДнейВМесяце(Дата) Экспорт

Возврат День(КонецМесяца(Дата));

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

И вызывать её из любого места конфигурации.-->

⚠️ Внимание: При работе с датами в учитывайте, что некоторые функции (например, ДнейВМесяце()) могут вести себя по-разному в разных версиях платформы. Для критических расчётов (например, в бухгалтерских отчётах) всегда тестируйте код на актуальной версии вашей конфигурации.