При разработке отчетов и обработок часто возникает задача манипуляции датами: требуется либо сдвинуть год на определенное количество лет вперед/назад, либо предоставить пользователю удобный интерфейс с раздельным выбором года и месяца вместо стандартного поля ввода даты. Разберем различные подходы к решению обеих задач.
Если требуется программно изменить год у существующей даты, самым надежным способом является добавление или вычитание месяцев. Попытка заменить год через строковые функции (например, СтрЗаменить) является грубой ошибкой, так как дата в 1С — это примитивный тип, а не строка, и строковое преобразование не учитывает корректность календаря.
Посмотрим на пример сдвига даты на 4 года вперед:
// Сдвиг даты на 4 года (4 * 12 = 48 месяцев)
ИсходнаяДата = '20160101';
НоваяДата = ДобавитьМесяц(ИсходнаяДата, 48); // Результат: 01.01.2020
Важная особенность: функция ДобавитьМесяц() корректно обрабатывает високосные года и дни на границах месяцев. Например, если прибавить 12 месяцев к дате 29.02.2016, платформа вернет 28.02.2017, так как 2017 год невисокосный. Это исключает возникновение исключений и ошибок переполнения даты.
Когда требуется произвольно подставить определенный год, месяц и день, оптимально использовать встроенный конструктор даты: Дата(Год, Месяц, Число, Час, Минута, Секунда).
Разберем пример подстановки нового года в исходную дату:
ИсходнаяДата = ТекущаяДата();
НовыйГод = 2025;
// Получаем составляющие исходной даты и собираем новую
День = День(ИсходнаяДата);
Месяц = Месяц(ИсходнаяДата);
// Проверяем краевой случай для 29 февраля
Если Месяц = 2 И День = 29 Тогда
// Если целевой год невисокосный, устанавливаем 28 февраля
Если НЕ ((НовыйГод % 4 = 0 И НовыйГод % 100 <> 0) ИЛИ (НовыйГод % 400 = 0)) Тогда
День = 28;
КонецЕсли;
КонецЕсли;
РезультирующаяДата = Дата(НовыйГод, Месяц, День, Час(ИсходнаяДата), Минута(ИсходнаяДата), Секунда(ИсходнаяДата));
Рассмотрим типовой сценарий: в отчете необходимо предоставить пользователю два отдельных элемента управления — выбор месяца (выпадающий список) и выбор года (поле со стрелками увеличения/уменьшения).
Разберем по шагам, как настроить форму и программную обработку:
Добавим на форму отчета два реквизита:
ВыбранныйГод — тип Число (длина 4, точность 0, неотрицательное). В свойствах реквизита при инициализации укажем текущий год: Год(ТекущаяДата()).ВыбранныйМесяц — тип Число (длина 2, точность 0, неотрицательное). Начальное значение: Месяц(ТекущаяДата()).Размещаем реквизит ВыбранныйГод на форме как ПолеВвода и задаем параметры:
Истина (появятся стрелки вверх/вниз для шага ±1).ЧГ=0 (это уберет разделитель тысяч, чтобы год не отображался как «2 024»).Регулирование вручную переопределять не требуется, так как платформа сама изменяет числовое значение. Достаточно назначить обработчик на событие ПриИзменении.Размещаем реквизит ВыбранныйМесяц на форме как ПолеВвода и задаем параметры:
Истина.1 — "Январь", 2 — "Февраль", ..., 12 — "Декабрь".При изменении месяца или года собираем результирующий период для параметров отчета или СКД:
&НаКлиенте
Процедура ВыбранныйГодПриИзменении(Элемент)
ОбновитьГраницыПериода();
КонецПроцедуры
&НаКлиенте
Процедура ВыбранныйМесяцПриИзменении(Элемент)
ОбновитьГраницыПериода();
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьГраницыПериода()
// Базовая дата — первое число выбранного месяца и года
БазоваяДата = Дата(ВыбранныйГод, ВыбранныйМесяц, 1);
// Получаем начало и конец периода
НачалоПериода = НачалоМесяца(БазоваяДата);
КонецПериода = КонецМесяца(БазоваяДата);
// Передаем даты в параметры отчета или СКД
УстановитьПараметрыОтчетаНаСервере(НачалоПериода, КонецПериода);
КонецПроцедуры
Если нет жесткого требования выносить год и месяц в разные поля ввода, наиболее универсальным решением для платформы 1С является использование реквизита с типом СтандартныйПериод.
Проанализируем его преимущества:
ПериодОтчета.ДатаНачала и ПериодОтчета.ДатаОкончания.