Как изменить год в дате и организовать раздельный выбор периода на форме в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Способ 1. Использование встроенной функции ДобавитьМесяц

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

Посмотрим на пример сдвига даты на 4 года вперед:


// Сдвиг даты на 4 года (4 * 12 = 48 месяцев)
ИсходнаяДата = '20160101';
НоваяДата = ДобавитьМесяц(ИсходнаяДата, 48); // Результат: 01.01.2020

Важная особенность: функция ДобавитьМесяц() корректно обрабатывает високосные года и дни на границах месяцев. Например, если прибавить 12 месяцев к дате 29.02.2016, платформа вернет 28.02.2017, так как 2017 год невисокосный. Это исключает возникновение исключений и ошибок переполнения даты.

Способ 2. Сборка даты из отдельных составляющих через конструктор

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

Разберем пример подстановки нового года в исходную дату:


ИсходнаяДата = ТекущаяДата();
НовыйГод = 2025;

// Получаем составляющие исходной даты и собираем новую
День = День(ИсходнаяДата);
Месяц = Месяц(ИсходнаяДата);

// Проверяем краевой случай для 29 февраля
Если Месяц = 2 И День = 29 Тогда
    // Если целевой год невисокосный, устанавливаем 28 февраля
    Если НЕ ((НовыйГод % 4 = 0 И НовыйГод % 100 <> 0) ИЛИ (НовыйГод % 400 = 0)) Тогда
        День = 28;
    КонецЕсли;
КонецЕсли;

РезультирующаяДата = Дата(НовыйГод, Месяц, День, Час(ИсходнаяДата), Минута(ИсходнаяДата), Секунда(ИсходнаяДата));

Способ 3. Организация раздельного выбора месяца и года на форме отчета

Рассмотрим типовой сценарий: в отчете необходимо предоставить пользователю два отдельных элемента управления — выбор месяца (выпадающий список) и выбор года (поле со стрелками увеличения/уменьшения).

Разберем по шагам, как настроить форму и программную обработку:

  1. Создание реквизитов формы:

    Добавим на форму отчета два реквизита:

    1. ВыбранныйГод — тип Число (длина 4, точность 0, неотрицательное). В свойствах реквизита при инициализации укажем текущий год: Год(ТекущаяДата()).
    2. ВыбранныйМесяц — тип Число (длина 2, точность 0, неотрицательное). Начальное значение: Месяц(ТекущаяДата()).
  2. Настройка элемента «Год» на форме:

    Размещаем реквизит ВыбранныйГод на форме как ПолеВвода и задаем параметры:

    1. Устанавливаем свойство КнопкаРегулирования в значение Истина (появятся стрелки вверх/вниз для шага ±1).
    2. В свойствах Формат и ФорматРедактирования указываем строку: ЧГ=0 (это уберет разделитель тысяч, чтобы год не отображался как «2 024»).
    3. Событие Регулирование вручную переопределять не требуется, так как платформа сама изменяет числовое значение. Достаточно назначить обработчик на событие ПриИзменении.
  3. Настройка элемента «Месяц» на форме:

    Размещаем реквизит ВыбранныйМесяц на форме как ПолеВвода и задаем параметры:

    1. Устанавливаем свойство РежимВыбораИзСписка в значение Истина.
    2. Заполняем СписокВыбора парами «Значение — Представление»: 1 — "Январь", 2 — "Февраль", ..., 12 — "Декабрь".
    3. Назначаем обработчик на событие ПриИзменении.
  4. Программный расчет границ периода:

    При изменении месяца или года собираем результирующий период для параметров отчета или СКД:

    
    &НаКлиенте
    Процедура ВыбранныйГодПриИзменении(Элемент)
        ОбновитьГраницыПериода();
    КонецПроцедуры
    
    &НаКлиенте
    Процедура ВыбранныйМесяцПриИзменении(Элемент)
        ОбновитьГраницыПериода();
    КонецПроцедуры
    
    &НаКлиенте
    Процедура ОбновитьГраницыПериода()
        // Базовая дата — первое число выбранного месяца и года
        БазоваяДата = Дата(ВыбранныйГод, ВыбранныйМесяц, 1);
        
        // Получаем начало и конец периода
        НачалоПериода = НачалоМесяца(БазоваяДата);
        КонецПериода = КонецМесяца(БазоваяДата);
        
        // Передаем даты в параметры отчета или СКД
        УстановитьПараметрыОтчетаНаСервере(НачалоПериода, КонецПериода);
    КонецПроцедуры
    

Способ 4. Использование типа «СтандартныйПериод»

Если нет жесткого требования выносить год и месяц в разные поля ввода, наиболее универсальным решением для платформы 1С является использование реквизита с типом СтандартныйПериод.

Проанализируем его преимущества:

  1. Пользователь получает встроенное окно выбора любого предопределенного периода: «Этот месяц», «Этот квартал», «Этот год», а также быстрый переход по годам и месяцам.
  2. Не требуется писать код для валидации високосных годов и обработки границ месяцев.
  3. Начало и конец периода получаются стандартными свойствами: ПериодОтчета.ДатаНачала и ПериодОтчета.ДатаОкончания.
← На главную