В процессе разработки в среде «1С:Предприятие» программисты регулярно сталкиваются с необходимостью манипуляции датами. Одной из классических задач является определение границ временных периодов, в частности — получение последнего дня (или последнего мгновения) года на основании произвольной даты. В этой статье мы разберем по шагам все доступные способы решения этой задачи: от самых простых встроенных функций до сложных конструкций в запросах и системе компоновки данных.
Самый очевидный и рекомендуемый способ получения конца года во встроенном языке 1С — это использование глобальной функции КонецГода(). Рассмотрим подробнее, как она работает. Данная функция принимает в качестве аргумента исходную дату и возвращает дату и время, соответствующие последней секунде указанного года.
Проанализируем пример кода:
// Предположим, ТекущаяДата = 29.08.2018 10:00:00
ИскомаяДата = КонецГода(ТекущаяДата);
// Результат будет: 31.12.2018 23:59:59
Важно помнить, что в 1С тип данных Дата всегда содержит и дату, и время. Функция КонецГода() устанавливает время в значение 23:59:59. Это критически важно при сравнении дат: если вы сравните 31.12.2018 12:00:00 с результатом функции КонецГода(), то первая дата будет меньше, так как она хронологически предшествует последней секунде года.
Иногда в учебных целях или при реализации специфической логики программисты используют арифметические методы. Разберем ситуацию, когда нам нужно вычислить конец года, опираясь на начало года и добавление интервалов. В 1С даты хранятся в секундах, поэтому вычитание единицы из даты означает вычитание одной секунды.
Рассмотрим следующий алгоритм:
Посмотрим на пример реализации:
ИсходнаяДата = Объект.Дата; // Допустим, 15.05.2023
НачалоСледующегоГода = ДобавитьМесяц(НачалоГода(ИсходнаяДата), 12);
ПоследнийМоментГода = НачалоСледующегоГода - 1;
Выясним причину, почему этот метод работает. Функция НачалоГода() возвращает 01.01.2023 00:00:00. При добавлении 12 месяцев мы получаем 01.01.2024 00:00:00. Вычитая одну секунду (единицу), мы откатываемся ровно на 31.12.2023 23:59:59. Чтобы гарантировать корректность времени, можно дополнительно обернуть результат в функцию КонецДня(), хотя математически в этом нет необходимости, если расчет был точен.
Бывают задачи, когда в отчете или интерфейсе требуется вывести именно дату 31.12 без указания времени 23:59:59 (или со временем 00:00:00). В этом случае использование КонецГода() может быть неудобным из-за лишних секунд. Проанализируем ситуацию и соберем дату вручную с помощью конструктора Дата().
Пример формирования даты:
ТекущийГод = Год(ИсходнаяДата);
ЧистаяДатаКонцаГода = Дата(ТекущийГод, 12, 31);
// Результат: 31.12.2023 00:00:00
Этот способ эффективен, если вам не нужны секунды для построения запросов по остаткам, а требуется просто константная дата последнего дня года для печатной формы или текстового сообщения.
Многие начинающие разработчики пытаются использовать функцию КонецГода() внутри запроса, но получают ошибку. Выясним причину: в языке запросов 1С используется другой синтаксис. Для получения границы периода служит универсальная функция КОНЕЦПЕРИОДА.
Разберем пример запроса, где нам нужно отобрать документы по конец года включительно:
ВЫБРАТЬ
Продажи.Ссылка КАК Ссылка,
Продажи.Дата КАК Дата
ИЗ
Документ.Продажи КАК Продажи
ГДЕ
Продажи.Дата МЕЖДУ &НачалоПериода И КОНЕЦПЕРИОДА(&ДатаКонца, ГОД)
В данном случае параметр ГОД указывает функции, что нужно вычислить именно конец календарного года для переданной даты. Это вернет 31 декабря 23:59:59. Использование КОНЕЦПЕРИОДА — это стандарт де-факто для работы с выборками данных, так как платформа оптимизирует такие выражения на уровне SQL-запроса.
В СКД при настройке параметров или вычисляемых полей мы также можем использовать функции работы с датами. Если в настройках отчета пользователь выбирает период, платформа часто предлагает «Стандартные периоды». Однако, если вам нужно программно в выражении параметра вычислить конец года, используйте синтаксис, аналогичный запросам.
Например, в поле «Выражение» для параметра ДатаКонца можно написать:
КонецПериода(&СтандартныйПериод.ДатаОкончания, "Год")
Или, если вы хотите использовать функции встроенного языка в вычисляемых полях, там доступна функция КонецГода() напрямую. Обратите внимание на различия в синтаксисе: в запросах пишется КОНЕЦПЕРИОДА(..., ГОД), а в выражениях СКД или встроенном языке — КонецГода(...).
Посмотрим на ситуацию со стороны пользователя. Если мы просто выведем результат функции КонецГода() в поле формы или ячейку табличного документа, пользователь увидит некрасивое время «23:59:59». Чтобы этого избежать, всегда применяйте форматную строку.
Рассмотрим пример правильного вывода:
ДатаДляПредставления = КонецГода(ТекущаяДата);
ТекстСообщения = "Отчет сформирован по " + Формат(ДатаДляПредставления, "ДФ=dd.MM.yyyy");
// Результат: Отчет сформирован по 31.12.2018
Использование параметра ДФ=dd.MM.yyyy (Дата Формат) позволяет скрыть временную часть, сохраняя при этом точность самого значения переменной для расчетов.
Подводя итог, выделим основные правила выбора метода:
КонецГода(). Это быстро, читаемо и надежно.КОНЕЦПЕРИОДА(Дата, ГОД).Формат(), чтобы не пугать пользователей секундами конца дня.Дата(Год(НужнаяДата), 12, 31).Эти знания помогут вам писать более чистый и понятный код, избегая ошибок при сравнении периодов и формировании сложных отчетов.