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

Программист 1С v8.3 (Обычные формы)
← На главную

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

Способ 1. Использование производственного календаря в типовых конфигурациях

В современных типовых решениях (например, "Бухгалтерия предприятия 3.0", "ЗУП 3.1", "ERP") на базе Библиотеки стандартных подсистем (БСП) реализован мощный механизм производственных календарей. Разберем, как это работает и почему это предпочтительный вариант.

Проанализируем возможности БСП. Если в вашей базе настроена "Интернет-поддержка", система автоматически загружает актуальные данные о праздниках и переносах с серверов 1С. Это избавляет программиста от необходимости вручную вносить даты каждый год. Для программного обращения к этим данным в БСП предусмотрен специальный программный интерфейс.

Выясним, как проверить конкретную дату. Для этого можно использовать метод общего модуля ПроизводственныеКалендари. Пример обращения к данным календаря может выглядеть следующим образом:


// Получаем данные производственного календаря
// КалендарьСсылка - ссылка на элемент справочника ПроизводственныеКалендари
// ПроверяемаяДата - дата, которую нужно проверить
ДанныеДня = ПроизводственныеКалендари.ДанныеПроизводственногоКалендаря(КалендарьСсылка, ПроверяемаяДата);

Если ДанныеДня.ВидДня = Перечисления.ВидыДнейПроизводственногоКалендаря.Рабочий Тогда
    // Это рабочий (банковский) день
ИначеЕсли ДанныеДня.ВидДня = Перечисления.ВидыДнейПроизводственногоКалендаря.Суббота 
    Или ДанныеДня.ВидДня = Перечисления.ВидыДнейПроизводственногоКалендаря.Воскресенье Тогда
    // Это выходной
КонецЕсли;

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

Способ 2. Программный расчет через списки праздников и переносов

Рассмотрим ситуацию, когда конфигурация не является типовой (например, старые версии "Альфа-Авто") или использование БСП по каким-то причинам невозможно. В этом случае мы можем написать собственную функцию. Проанализируем алгоритм, предложенный в обсуждении, который позволяет вычислить "вчерашнюю" банковскую дату.

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


Функция ВчерашняяБанковскаяДата(Дата = Неопределено) Экспорт
    // Формируем список государственных праздников
    Праздники = Новый СписокЗначений;
    Праздники.Добавить(Дата("20230101")); // Пример для наглядности
    Праздники.Добавить(Дата("20230501"));
    Праздники.Добавить(Дата("20230509"));
    
    // Формируем список официальных переносов (когда суббота становится рабочей)
    Переносы = Новый СписокЗначений;
    // Сюда добавляются даты рабочих суббот
    
    Дата = ?(Дата = Неопределено, ТекущаяДата(), Дата);
    // Берем начало предыдущего дня
    ВчерашняяДата = НачалоДня(НачалоДня(Дата) - 1);

~МеткаПроверки:    
    // 1. Проверяем, не является ли день рабочей субботой по переносу
    Если Переносы.НайтиПоЗначению(ВчерашняяДата) <> Неопределено Тогда
        Возврат ВчерашняяДата;
    КонецЕсли;
    
    // 2. Исключаем стандартные выходные (суббота - 6, воскресенье - 7)
    Если ДеньНедели(ВчерашняяДата) = 6 Тогда        
        ВчерашняяДата = ВчерашняяДата - 24*60*60; // Сдвигаемся еще на день назад
        Перейти ~МеткаПроверки;
    ИначеЕсли ДеньНедели(ВчерашняяДата) = 7 Тогда    
        ВчерашняяДата = ВчерашняяДата - 24*60*60;
        Перейти ~МеткаПроверки;
    КонецЕсли; 
    
    // 3. Проверяем на вхождение в список праздников
    Если Праздники.НайтиПоЗначению(ВчерашняяДата) <> Неопределено Тогда
        ВчерашняяДата = ВчерашняяДата - 24*60*60;
        Перейти ~МеткаПроверки;
    КонецЕсли;
    
    Возврат ВчерашняяДата;
КонецФункции

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

Способ 3. Работа в специализированных отраслевых решениях (Альфа-Авто)

В конфигурациях типа "Альфа-Авто" (от Рарус) часто используется регистр сведений График работ календарный. Проанализируем специфику этой системы. В ней календарь может заполняться полуавтоматически, но праздничные дни часто требуют ручной корректировки.

Разберем по шагам, как настроить такой календарь:

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

Этот метод надежен тем, что позволяет пользователю самостоятельно оперативно менять график, не дожидаясь обновления программы от разработчика или вмешательства программиста.

Нюансы: Банковский день vs Операционный день

Выясним важную техническую и юридическую деталь. Понятие "Банковский день" не всегда тождественно понятию "Рабочий день по ТК РФ".

Во-первых, существуют региональные праздники. Если ваш контрагент находится в другом субъекте РФ, его банк может не работать в день, который для вашего региона является рабочим.

Во-вторых, существует понятие "Операционного дня". Это время, в течение которого банк принимает платежные документы для исполнения "день в день". Обычно это время ограничено (например, до 16:00 или 17:00). Все, что отправлено позже, даже в рабочий день, фактически уйдет следующей банковской датой. При автоматизации выгрузки платежек из 1С крайне желательно учитывать этот временной порог (cutoff time).

Современные подходы: Использование внешних API

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

  1. Формируем HTTP-запрос к сервису, передавая в параметрах нужную дату.
  2. Сервис возвращает код (0 — рабочий, 1 — выходной, 2 — праздничный и т.д.).
  3. В 1С обрабатываем этот ответ через HTTPЗапрос и HTTPСоединение.

Это позволяет системе динамически определять статус дня, опираясь на внешние актуальные базы данных законодательства.

Подводя итог, выбор метода зависит от вашей конфигурации. В современных системах лучше использовать ПроизводственныеКалендари из БСП, в кастомных или устаревших — комбинацию регистра сведений и программной проверки списков исключений.

← На главную