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

В этой статье мы разберем все возможные способы вычитания года из даты в 1С — от элементарных действий в пользовательском режиме до сложных программных конструкций. Вы узнаете, какой метод выбрать для вашей задачи, как избежать типичных ошибок и почему иногда простой арифметический подход работает хуже, чем специализированные функции платформы. Материал актуален для 1С 8.3 и 8.2 (с учетом особенностей), а также для большинства конфигураций: Бухгалтерия 3.0, ЗУП 3.1, УТ 11, ERP 2 и кастомизированных решений.

1. Простейший способ: ручное вычитание в пользовательском режиме

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

Как это работает:

  • 📅 Откройте документ или отчет, где требуется изменить дату.
  • 🖱️ Кликните по полю с датой — появится календарь.
  • ⏪ В верхней части календаря нажмите на стрелку "вверх" (↑) рядом с годом — это уменьшит год на единицу.
  • ✅ Подтвердите изменения кнопкой ОК.

Этот метод подходит для разовых операций, но имеет ограничения:

  • ❌ Не работает в пакетном режиме (например, для массового изменения дат в таблице).
  • ❌ Не учитывает автоматически високосные годы при сдвиге на несколько лет.
  • ❌ Неприменим в отчетах с динамическими датами.
💡

Если дата в поле подсвечивается красным — проверьте формат хранения (возможно, это строка, а не тип Дата).

2. Арифметические операции с датами: плюсы и подводные камни

Самый очевидный способ вычесть год — использовать арифметику. В даты хранятся как числа (количество дней от 01.01.0001), поэтому можно просто отнять 365 дней. Но этот подход чреват ошибками!

Пример кода (в модуле объекта или обработке):

НоваяДата = ТекущаяДата - 365;

Проблемы этого метода:

  • 🔴 Високосные годы: если дата попадает на 29 февраля, после вычитания 365 дней получится 28.02.XXXX — это может сломать логику расчетов.
  • 🔴 Переход через столетия: при вычитании из 01.01.2100 результат будет некорректным из-за особенностей григорианского календаря.
  • 🔴 Нечитаемость кода: через месяц вы забудете, почему именно 365, а не 366.
📊 Какой способ вычитания дат вы используете чаще?
Арифметика (365 дней)
Встроенная функция НачалоГода()
Запросы 1С
Собственная функция
Другой вариант

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

// Вычитаем год с учетом високосности (неточный метод!)

НоваяДата = ТекущаяДата - 365;

3. Встроенные функции 1С для работы с датами

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

Основные функции:

Функция Описание Пример использования
НачалоГода() Возвращает дату 1 января заданного года НачалоГода(Дата) - 1 — последний день предыдущего года
ДобавитьМесяц() Добавляет/вычитает месяцы (в т.ч. годы, как 12 месяцев) ДобавитьМесяц(Дата, -12) — вычитает год
Год() Возвращает год из даты НачалоГода(Год(Дата) - 1) — первый день предыдущего года

Самый надежный способ вычесть год:

НоваяДата = ДобавитьМесяц(ТекущаяДата, -12);

Почему это лучше арифметики:

  • ✅ Автоматически учитывает високосные годы.
  • ✅ Корректно работает при переходе через столетия.
  • ✅ Код становится самодокументируемым.
💡

Функция ДобавитьМесяц() — лучший выбор для вычитания лет, так как она учитывает все календарные особенности.

4. Вычитание года в запросах 1С

Если вам нужно изменить дату прямо в запросе (например, для фильтрации или группировки данных), используйте конструкцию ДАТАВРЕМЯ с арифметикой или функцию ДОБАВИТЬКДАТЕ.

Пример с арифметикой (осторожно, см. раздел 2!):

ВЫБРАТЬ

ДатаДокумента КАК ИсходнаяДата,

ДатаДокумента - 365 КАК ДатаМинусГод

ИЗ

Документ.ЗаказПокупателя

Более надежный вариант с ДОБАВИТЬКДАТЕ:

ВЫБРАТЬ

ДатаДокумента КАК ИсходнаяДата,

ДОБАВИТЬКДАТЕ(ДатаДокумента, ГОД, -1) КАК ДатаМинусГод

ИЗ

Документ.ЗаказПокупателя

Особенности работы с датами в запросах:

  • 📊 В результатах запроса даты возвращаются в формате ДатаВремя, даже если в таблице хранится только дата.
  • 🔍 Для фильтрации по дате минус год используйте ГДЕ ДатаДокумента >= ДОБАВИТЬКДАТЕ(ТекущаяДата(), ГОД, -1).
  • ⚡ Функция ДОБАВИТЬКДАТЕ работает медленнее арифметики, но точнее.
Что делать, если запрос возвращает неверный формат даты?

Если в результате запроса дата отображается с временем (например, 01.01.2023 00:00:00), используйте функцию НАЧАЛОПЕРИОДА:

НАЧАЛОПЕРИОДА(ДатаМинусГод, "ДЕНЬ")

Это обрежет время, оставив только дату.

5. Программное вычитание года с обработкой исключений

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

Пример кода с обработкой ошибок:

Функция ВычестьГод(Знач Дата)

Попытка

Возврат ДобавитьМесяц(Дата, -12);

Исключение

// Если дата некорректна (например, 29.02.2023 после вычитания года)

Сообщить("Ошибка при вычитании года: " + ОписаниеОшибки());

Возврат Неопределено;

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

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

Когда это необходимо:

  • 🔄 При пакетной обработке тысяч документов (чтобы не прервать выполнение из-за одной ошибки).
  • 📤 При обмене данными с другими системами, где формат даты может отличаться.
  • 🛡️ В критически важных расчетах (например, начисление зарплаты или налогов).

Поле содержит дату, а не строку|Дата не пустая (Дата = '00010101')|Учет временных зон не требуется|Формат даты совпадает с ожидаемым

-->

Для работы с периодами (например, "минус год от текущей даты до конца месяца") используйте комбинацию функций:

ДатаНачала = НачалоМесяца(ДобавитьМесяц(ТекущаяДата(), -12));

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

6. Вычитание года в отчетах и СКД

В системе компоновки данных (СКД) даты часто используются для динамических периодов. Чтобы вычесть год в настройках отчета, применяйте параметры или вычисляемые поля.

Пример настройки параметра в СКД:

  1. Откройте схему компоновки данных.
  2. Добавьте новый параметр типа Дата.
  3. В выражении для значения по умолчанию укажите:
    ДобавитьМесяц(ТекущаяДата(), -12)
  4. Используйте этот параметр в фильтрах или группировках.

Если нужно сравнить данные "год к году" в отчете:

  • 📈 Добавьте два набора данных: для текущего периода и для периода минус год.
  • 🔗 Свяжите их по измерениям (например, по номенклатуре или контрагенту).
  • 📊 Используйте вычисляемые ресурсы для расчета отклонений.
💡

В СКД для удобства можно создать пользовательское поле с формулой Год(Дата) - 1, чтобы не пересчитывать даты в каждом запросе.

7. Особенности для разных конфигураций 1С

В некоторых конфигурациях (например, ЗУП 3.1 или ERP 2) даты могут храниться в нестандартных форматах или требовать дополнительной обработки. Рассмотрим ключевые нюансы.

Таблица особенностей по конфигурациям:

Конфигурация Особенность Рекомендация
Бухгалтерия 3.0 Дата документа может быть привязана к периоду закрытия месяца Проверяйте доступность даты функцией ДатаДоступна()
ЗУП 3.1 Дата начисления зарплаты не может быть раньше даты приема на работу Добавляйте проверку: Если ДатаМинусГод >= ДатаПриема Тогда...
УТ 11 В заказах дата отгрузки не может быть раньше даты документа Используйте Максимум(ДатаДокумента, ДатаМинусГод)

Для управленческих конфигураций (например, ERP) важно учитывать:

  • 🔒 Права доступа: пользователь может не иметь прав на изменение дат в некоторых документах.
  • 🔄 Версионность: при изменении даты может потребоваться создание новой версии документа.
  • 📌 Бизнес-логика: в некоторых случаях дата связана с графиками, планами или бюджетами.
Как проверить, доступна ли дата для изменения?

Используйте функцию ДатаДоступна() из модуля документа:

Если НЕ ДатаДоступна(ДатаМинусГод, ВидДокумента.ЗаказПокупателя) Тогда

Сообщить("Дата " + Формат(ДатаМинусГод, "ДФ=dd.MM.yyyy") + " закрыта для редактирования!");

КонецЕсли;

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

Даже опытные разработчики иногда допускают ошибки при работе с датами. Вот самые распространенные из них и способы их предотвращения.

Ошибка 1: Игнорирование формата хранения

⚠️ Внимание: Если поле в базе имеет тип Строка, а не Дата, то функция ДобавитьМесяц() не сработает! Сначала преобразуйте строку в дату с помощью Дата(Значение).

Ошибка 2: Неучет временной зоны

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

Ошибка 3: Попытка вычесть год из пустой даты

Если дата не инициализирована (Дата = '00010101'), то арифметика или функции вернут некорректный результат. Всегда добавляйте проверку:

Если Дата = '00010101' Тогда

Возврат Неопределено;

КонецЕсли;

Ошибка 4: Забывают про високосные годы при массовых операциях

При обработке тысяч документов разница в один день (28.02 vs 29.02) может привести к ошибкам в отчетах. Используйте ДобавитьМесяц() вместо арифметики.

Ошибка 5: Не учитывают границы периодов

⚠️ Внимание: В Бухгалтерии 3.0 дата документа не может быть раньше даты начала ведения учета. Перед вычитанием года проверяйте это ограничение через ПараметрыУчета.ДатаНачалаВеденияУчета.

Чтобы минимизировать ошибки, используйте этот чек-лист перед изменением дат:

Дата инициализирована (Дата <> '00010101')|Тип поля — Дата, а не строка|Учет временных зон не требуется|Дата попадает в разрешенный период|Нет привязки к закрытым периодам

-->

FAQ: Частые вопросы по вычитанию года в 1С

Можно ли вычесть год из даты в отчете без изменения исходных данных?

Да, в СКД или в самом отчете можно использовать вычисляемые поля. Например, добавьте колонку с формулой ДОБАВИТЬКДАТЕ(ДатаДокумента, ГОД, -1). Это не изменит данные в базе, но покажет дату минус год в отчете.

Почему после вычитания года дата становится 28.02 вместо 29.02?

Это происходит из-за особенностей обработки високосных годов. Функция ДобавитьМесяц() автоматически корректирует дату, если в целевом году 29 февраля не существует. Чтобы сохранить 29.02, используйте арифметику с проверкой:

Если День(ИсходнаяДата) = 29 И Месяц(ИсходнаяДата) = 2 Тогда

НоваяДата = НачалоГода(Год(ИсходнаяДата) - 1) + 59; // 29 февраля — 59-й день года

Иначе

НоваяДата = ДобавитьМесяц(ИсходнаяДата, -12);

КонецЕсли;

Как вычесть год в мобильном приложении 1С?

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

// Серверная функция

Функция ПолучитьДатаМинусГод(Дата) Экспорт

Возврат ДобавитьМесяц(Дата, -12);

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

Можно ли вычесть год из даты в внешней обработке?

Да, во внешней обработке доступны все стандартные функции работы с датами. Главное — убедиться, что обработка подключена к базе с совместимой версией платформы (8.3.х). Пример кода для обработки:

Процедура КомандаВычестьГод(Команда)

ДатаРез = ДобавитьМесяц(ТекущаяДата(), -12);

Сообщить("Дата минус год: " + Формат(ДатаРез, "ДФ=dd.MM.yyyy"));

КонецПроцедуры

Что делать, если после вычитания года дата становится невалидной (например, 31.04.2023)?

Такие даты возникают, если исходная дата была 31.03.2026, а после вычитания года пытается вернуть 31.02.2023. Платформа автоматически корректирует дату до последнего валидного дня месяца (28.02.2023 или 29.02.2023). Если это критично, используйте явную проверку:

НоваяДата = ДобавитьМесяц(ИсходнаяДата, -12);

Если День(НоваяДата) <> День(ИсходнаяДата) Тогда

Сообщить("Дата скорректирована с " + День(ИсходнаяДата) + " на " + День(НоваяДата));

КонецЕсли;