Работа с временными интервалами является одной из базовых задач при разработке конфигураций на платформе 1С:Предприятие. Часто возникает необходимость рассчитать срок действия договора, определить дату следующего платежа или сформировать отчетный период. Для этих целей система предоставляет встроенный инструментарий, который корректно обрабатывает високосные годы и разное количество дней в месяцах.
В языке запросов и встроенном языке 1С существует несколько подходов к изменению дат. Выбор конкретного метода зависит от того, нужно ли вам добавить строго календарный день, месяц или год, а также от контекста выполнения кода. Неправильное использование функций может привести к логическим ошибкам, особенно при переходе через конец месяца.
В этой статье мы подробно разберем основные функции для манипуляции датами, рассмотрим их отличия и приведем практические примеры использования в коде. Вы научитесь избегать типичных ошибок при расчете временных интервалов в вашей базе данных.
Основная функция ДобавлениеМесяца
Самым универсальным и часто используемым инструментом является функция ДобавлениеМесяца. Несмотря на название, она позволяет добавлять не только месяцы, но и дни, и годы. Это происходит за счет указания соответствующего значения в третьем параметре функции.
Синтаксис функции предельно прост: первым аргументом передается исходная дата, вторым — количество добавляемых периодов, а третьим — тип периода. Тип периода задается перечислением ПериодДатаВремя. Если вам нужно прибавить именно один день, вы должны указать константу ПериодДатаВремя.День.
Главное преимущество этого метода заключается в его «умном» поведении при переходе через границы месяцев. Если вы добавляете месяц к дате 31 января, система автоматически скорректирует результат до 28 или 29 февраля, а не выдаст ошибку или неверную дату. Это критически важно для бухгалтерских расчетов.
⚠️ Внимание: При добавлении месяцев к датам конца месяца (29, 30, 31 число) результат может быть смещен на последний день целевого месяца, если в нем меньше дней. Это штатное поведение платформы, а не ошибка.
Рассмотрим пример кода, где мы берем текущую дату и прибавляем к ней один день. Обратите внимание, как явно указывается тип периода для избежания неоднозначности интерпретации числа.
ИсходнаяДата = ТекущаяДата();
НоваяДата = ДобавлениеМесяца(ИсходнаяДата, 1, ПериодДатаВремя.День);
Сообщить("Новая дата: " + НоваяДата);
Использование функции СдвигДаты
Альтернативным способом, который появился в более современных версиях платформы, является функция СдвигДаты. Она часто используется в запросах и предоставляет более гибкий механизм работы с временными интервалами, особенно когда требуется сложная логика сдвига.
В отличие от ДобавлениеМесяца, функция СдвигДаты может принимать интервалы в виде строк или структур, что позволяет комбинировать разные единицы измерения времени в одной операции. Однако для простой задачи «прибавить день» она может показаться избыточной.
Тем не менее, знание этой функции необходимо разработчику, так как она является стандартом для работы с датами в языке запросов 1С. В запросе вы не сможете использовать ДобавлениеМесяца так же свободно, как во встроенном языке, поэтому СдвигДаты становится основным инструментом.
Для добавления дней в запросах 1С используйте функцию СДВИГДАТЫ(Дата, Количество, "День"). Это обеспечит корректную работу на уровне СУБД.
Пример использования сдвига даты на один день вперед выглядит следующим образом. Здесь мы используем строковое представление периода, что допустимо в большинстве контекстов выполнения.
ДатаОтчета = '20231231';
ДатаСледДня = СдвигДаты(ДатаОтчета, 1, "День");
Ручной расчет через секунды
Иногда разработчики прибегают к «низкоуровневому» методу расчета, работая напрямую с количеством секунд. В платформе 1С дата хранится как количество секунд, прошедших с начала эры. Зная это, можно просто прибавить количество секунд в сутках к значению даты.
В одних сутках содержится 86400 секунд. Этот метод может быть полезен в специфических ситуациях оптимизации или при работе с legacy-кодом, где использование функций считается слишком дорогим. Однако такой подход лишен защиты от ошибок перехода через месяцы, если вы начнете оперировать месяцами.
Для добавления одного дня вам достаточно выполнить простую арифметическую операцию. Этот способ работает быстро, но делает код менее читаемым для других разработчиков, которые могут не знать магическое число 86400.
- 🕒 Один день равен 24 часам.
- ⏱️ Один час содержит 3600 секунд.
- 🔢 Итого: 24 * 3600 = 86400 секунд.
Если вы решите использовать этот метод, убедитесь, что результат преобразуется обратно в тип Дата, если это необходимо для дальнейшего вывода или сохранения в базу данных. В современном коде предпочтение отдается функциям-оберткам.
СекундВДне = 86400;
НоваяДата = Дата + СекундВДне;
Особенности работы с високосными годами
Одной из самых частых проблем при работе с датами является 29 февраля. При написании кода важно учитывать, что високосный год наступает не каждые 4 года строго, а по более сложному правилу григорианского календаря. Платформа 1С:Предприятие берет эту логику на себя.
Если вы используете функции ДобавлениеМесяца или СдвигДаты, вам не нужно писать дополнительные проверки на високосность. Система автоматически определит количество дней в феврале целевого года. Это экономит время и снижает вероятность возникновения багов в продакшене.
Однако, если вы используете ручной расчет или кастомные алгоритмы, вы обязаны реализовать проверку. Иначе при добавлении 365 дней к дате 1 марта високосного года вы можете попасть на 28 февраля следующего года вместо 1 марта, что нарушит логику бизнес-процесса.
Правило високосного года
Год является високосным, если он делится на 4, но не делится на 100, за исключением случаев, когда он делится на 400. Например, 2000 год был високосным, а 1900 — нет.
В таблице ниже приведены примеры поведения системы при добавлении дней и месяцев к различным датам, чтобы вы могли наглядно увидеть разницу в результатах.
| Исходная дата | Операция | Результат | Комментарий |
|---|---|---|---|
| 31.01.2023 | + 1 месяц | 28.02.2023 | Корректировка конца месяца |
| 28.02.2023 | + 1 день | 01.03.2023 | Обычный переход |
| 28.02.2026 | + 1 день | 29.02.2026 | Високосный год |
| 31.12.2023 | + 1 день | 01.01.2026 | Переход через год |
Работа с датами в запросах 1С
Когда речь заходит о выборке данных из базы, подход к изменению дат меняется. В языке запросов 1С нельзя просто вызвать функцию встроенного языка. Здесь используются специальные конструкции, которые транслируются в SQL-подобные команды для СУБД.
Для добавления дней в запросе чаще всего используется функция СДВИГДАТЫ. Она позволяет динамически формировать условия отбора. Например, если вам нужно выбрать все документы за завтрашний день, вы будете сдвигать текущую дату в условии ГДЕ.
Если вы сравниваете даты без времени, может возникнуть ситуация, когда запись с временем 10:00 не попадет в выборку по дате 00:00. Поэтому при работе с периодами часто используют функцию НАЧАЛОДНЯ или КОНЕЦДНЯ.
Пример фрагмента запроса, где мы формируем дату окончания периода путем добавления одного дня к дате начала:
ВЫБРАТЬ
Документы.Ссылка,
Документы.Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК Документы
ГДЕ
Документы.Дата МЕЖДУ &НачалоПериода И СДВИГДАТЫ(&НачалоПериода, 1, "День")
Типичные ошибки и лучшие практики
При разработке часто встречаются ситуации, когда код работает локально на тестовой базе, но выдает ошибки на мощном сервере под высокой нагрузкой. Часто это связано с некорректной обработкой временных зон или летнего времени, хотя в 1С 8.3 эта проблема решена лучше, чем в предыдущих версиях.
Одной из распространенных ошибок является попытка добавить месяц путем простого увеличения номера месяца в структуре даты. Такой подход гарантированно сломается в январе (месяц 13?) или при переходе через февраль. Всегда используйте штатные функции платформы.
Также стоит избегать хранения дат в виде строк в регистрах сведений. Это усложняет выборки и требует постоянного преобразования типов, что снижает производительность системы. Используйте тип Дата везде, где это возможно.
⚠️ Внимание: Интерфейсы и поведение некоторых функций могут незначительно отличаться в разных релизах платформы 1С:Предприятие. Всегда проверяйте актуальность синтаксиса в справке по вашей версии конфигурации.
Для закрепления материала рекомендуется пройти небольшой чек-лист перед внедрением кода в рабочую базу. Это поможет избежать досадных опечаток и логических несостыковок.
☑️ Проверка кода работы с датами
Часто задаваемые вопросы (FAQ)
Как прибавить к дате ровно 24 часа, игнорируя переход на летнее время?
Если вам нужно добавить именно физический интервал времени, а не календарный день, используйте прибавление секунд (86400) или функцию ДобавлениеВремя. Календарные функции могут учитывать переходы времени, что иногда меняет длительность суток.
Что вернет функция, если добавить месяц к 31 марта?
Функция ДобавлениеМесяца(Дата(2023, 03, 31), 1, ПериодДатаВремя.Месяц) вернет 30 апреля, так как в апреле всего 30 дней. Система автоматически обрежет дату до последнего валидного дня месяца.
Можно ли вычитать дни с помощью этих функций?
Да, безусловно. Просто передайте отрицательное значение во второй параметр. Например, ДобавлениеМесяца(Дата, -5, ПериодДатаВремя.День) отнимет 5 дней от указанной даты.
В чем разница между ДатаВремя и Дата в контексте сложения?
Тип ДатаВремя содержит информацию о часах, минутах и секундах, а тип Дата хранит только дату (время обнуляется). При добавлении дней к типу Дата время останется нулевым, а к ДатаВремя — сохранится исходное время суток.
Использование встроенных функций 1С для работы с датами гарантирует корректный учет високосных лет и разной длительности месяцев, что критически важно для бухгалтерского учета.