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

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

В данной статье мы подробно рассмотрим все доступные способы уменьшения даты на сутки. Мы проанализируем встроенные функции платформы, разберем особенности работы с типом Дата и приведем примеры кода, которые можно сразу использовать в ваших конфигурациях. Понимание этих механизмов поможет избежать распространенных ошибок при формировании временных интервалов.

Основы работы с типом Дата в 1С

Прежде чем приступать к вычитанию дней, необходимо четко представлять, как устроен тип данных Дата внутри платформы. Любая дата в 1С — это момент времени с точностью до секунды. Когда вы создаете переменную типа Дата, вы фактически работаете с числовым значением, которое система интерпретирует как конкретный момент на временной шкале. Это фундаментальное свойство позволяет использовать стандартные арифметические операторы.

Однако прямой перевод дней в секунды может быть ошибочным подходом для календарных расчетов. В сутках всегда 86400 секунд, но при переходе через границы месяцев или лет простое вычитание этого числа может привести к неочевидным результатам, если не учитывать временные зоны или летнее время (хотя в современных версиях платформы это нивелировано). Более надежным способом является использование специализированных функций, предназначенных именно для календарных сдвигов.

Для корректной работы с датами программист должен учитывать, что операционная система и сама платформа могут по-разному интерпретировать "начало" и "конец" дня. При вычитании одного дня важно понимать, сохраняем ли мы время суток или сбрасываем его. Например, если от даты 25.01.2026 15:30:00 отнять сутки математически, мы получим 24.01.2026 15:30:00. Если же нам нужно просто перейти на вчерашний день, игнорируя время, подход будет иным.

Ключевым моментом является понимание того, что 1С предоставляет мощный инструментарий для манипуляций со временем, который абстрагирует разработчика от низкоуровневых вычислений. Использование встроенных средств делает код более читаемым и защищенным от ошибок, связанных с человеческим фактором при подсчете секунд.

💡

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

Использование функции ДобавлениеДаты

Самым правильным и рекомендуемым способом изменить дату на определенное количество дней является использование встроенной функции ДобавлениеДаты. Несмотря на название, эта функция универсальна: она позволяет как прибавлять, так и отнимать периоды времени. Для вычитания дня достаточно передать отрицательное значение в параметр количества дней.

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

Рассмотрим пример использования этой функции в коде модуля:

ИсходнаяДата = ТекущаяДата();

НоваяДата = ДобавлениеДаты(ИсходнаяДата, -1, Период.День);

Сообщить("Вчера было: " + НоваяДата);

В данном примере мы берем текущий момент времени и сдвигаем его ровно на одни сутки назад. Функция автоматически учтет все нюансы календаря. Если сегодня 1 марта, то результатом будет 28 или 29 февраля, в зависимости от года. Это избавляет разработчика от необходимости писать сложные условия для проверки количества дней в месяце.

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

☑️ Проверка корректности вычитания даты

Выполнено: 0 / 4

Арифметические операции с датами

Платформа 1С позволяет выполнять прямые арифметические действия над объектами типа Дата. Вы можете вычитать из даты число, которое будет интерпретироваться как количество секунд. Это дает гибкость, но требует от программиста большей внимательности. Чтобы отнять один день таким способом, необходимо вычесть количество секунд в сутках.

Количество секунд в одном дне равно 86400 (24 часа 60 минут 60 секунд). Следовательно, выражение Дата - 86400 вернет дату, отстоящую ровно на 24 часа назад. Этот метод часто используется в быстрых скриптах или когда требуется высокая производительность вычислений, хотя разница в скорости по сравнению со встроенными функциями обычно пренебрежимо мала.

Пример арифметического вычитания:

ТекущаяДата = ТекущаяДата();

Вчера = ТекущаяДата - 86400;

// Или с использованием константы для читаемости

СекундВДне = 24 60 60;

Вчера = ТекущаяДата - СекундВДне;

Однако у этого подхода есть существенный недостаток: он не учитывает календарную логику так явно, как функция ДобавлениеДаты. Хотя результат будет идентичным для сдвига на целые сутки, код становится менее читаемым для других разработчиков. Фраза Минус 86400 не сразу говорит о том, что мы переходим на вчерашний день, в отличие от явного вызова функции с параметром Период.День.

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

⚠️ Внимание: При использовании арифметического вычитания убедитесь, что вы работаете с полным значением даты и времени. Если дата усечена или приведена к другому типу, результат может быть непредсказуемым.

Особенности переходов через месяц и год

Одной из самых частых проблем при работе с датами является корректный переход через границы календарных периодов. Что произойдет, если от 1 марта отнять один день? Логически мы должны получить последнее число февраля. При использовании функции ДобавлениеДаты этот переход выполняется автоматически и без ошибок.

Система сама определяет, сколько дней в текущем месяце и является ли год високосным. Високосный год добавляет один день в феврале (29 вместо 28), и функция ДобавлениеДаты учитывает это правило григорианского календаря. Разработчику не нужно писать дополнительные проверки вида Если Год(Дата) Мод 4 = 0 Тогда.., что существенно упрощает код и снижает вероятность логических ошибок.

Аналогично обстоят дела с переходом через год. Если от 1 января 2026 года отнять один день, мы получим 31 декабря 2023 года. Платформа корректно уменьшает значение года. Это критически важно для расчетов, связанных с годовыми отчетами, где ошибка в один день может привести к попаданию данных в неверный отчетный период.

В таблице ниже приведены примеры поведения системы при вычитании одного дня в пограничных ситуациях:

Исходная дата Операция Результат Особенность
01.03.2023 Минус 1 день 28.02.2023 Обычный год
01.03.2026 Минус 1 день 29.02.2026 Високосный год
01.01.2026 Минус 1 день 31.12.2023 Смена года
01.06.2026 Минус 1 день 31.05.2026 Смена месяца (30 дней)

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

Как 1С определяет високосный год?

Система использует алгоритм григорианского календаря: год является високосным, если он делится на 4, но не делится на 100, за исключением случаев, когда он делится на 400. Например, 2000 год был високосным, а 1900 — нет.

Работа с началом и концом дня

Часто при вычитании дня требуется не просто сдвинуть временную метку на 24 часа, а получить именно календарную дату вчерашнего дня, обнулив время. Например, для выборки документов за "вчерашний день" нам нужен интервал с 00:00:00 до 23:59:59 вчерашних суток. Для этого используются функции НачалоДня и КонецДня.

Функция НачалоДня(Дата) возвращает дату с установленным временем 00:00:00. Комбинируя её с вычитанием, мы можем получить точную границу периода. Это стандартный паттерн при построении запросов к базе данных, где условия часто накладываются на начало периода.

Пример получения начала вчерашнего дня:

ВчераНачало = НачалоДня(ДобавлениеДаты(ТекущаяДата(), -1, Период.День));

// Результат будет вроде 24.01.2026 00:00:00

Если же вам нужно получить конец вчерашнего дня (последнюю секунду), используется функция КонецДня. Она устанавливает время в 23:59:59. Понимание разницы между этими функциями критично для корректной работы отчетов. Ошибка в выборе границы может привести к тому, что документы, созданные в последние секунды дня, не попадут в выборку или, наоборот, попадут в отчет следующего дня.

Также стоит упомянуть функцию ПолучитьПериод, которая позволяет сразу получить структуру с началом и концом дня, недели или месяца. Это удобно, когда нужно задать фильтр для таблицы или отчета. Вы можете получить период вчерашнего дня одной строкой кода, что делает программу более компактной и читаемой.

При работе с временными зонами помните, что функции начала и конца дня используют время локального компьютера пользователя или сервера, в зависимости от контекста выполнения кода. В клиент-серверном варианте это может привести к рассинхронизации, если не контролировать временную зону явно.

💡

Для корректного формирования отчетных периодов всегда используйте комбинацию функций ДобавлениеДаты и НачалоДня/КонецДня, чтобы избежать попадания документов смежных дней в выборку.

Использование в запросах и консоли

В языке запросов 1С также поддерживаются операции с датами, но синтаксис немного отличается от встроенного языка. В тексте запроса вы можете использовать функцию ДАТАДОБАВИТЬ (или DATEADD в некоторых версиях синтаксиса) для сдвига дат прямо в условии выборки. Это позволяет перенести вычисления на сторону СУБД, что повышает производительность.

Пример условия в запросе для отбора документов за вчерашний день:

ВЫБРАТЬ

Документ.Ссылка,

Документ.Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Дата МЕЖДУ НАЧАЛОДНЯ(ДАТАДОБАВИТЬ(&ТекущаяДата, -1, ДЕНЬ))

И КОНЕЦДНЯ(ДАТАДОБАВИТЬ(&ТекущаяДата, -1, ДЕНЬ))

Здесь параметр &ТекущаяДата передается из кода 1С, а функции НАЧАЛОДНЯ и КОНЕЦДНЯ вычисляются внутри запроса. Такой подход является наиболее эффективным для больших баз данных, так как позволяет использовать индексы по полю Дата.

В консоли запросов или при отладке кода удобно использовать выражения для быстрой проверки дат. Вы можете ввести ДобавлениеДаты(ТекущаяДата(), -1, Период.День) прямо в поле выражений отладчика, чтобы увидеть результат. Это помогает быстро верифицировать логику работы программы без необходимости запускать весь отчет целиком.

День, как во встроенном языке. Это частая ошибка начинающих разработчиков при переносе кода из модуля в текст запроса.

⚠️ Внимание: В запросах 1С функции работы с датами чувствительны к локали и настройкам СУБД. Всегда тестируйте запросы на тестовой копии базы перед выгрузкой в промышленную эксплуатацию.

📊 Какой способ вычитания даты вы используете чаще?
Функция ДобавлениеДаты
Арифметика (минус секунды)
В запросах (DATEADD)
Через начало/конец дня

Частые ошибки и рекомендации

При работе с датами разработчики часто допускают типовые ошибки, которые могут привести к некорректной работе программы. Одна из самых распространенных — попытка вычесть день из строкового представления даты. Тип Строка не поддерживает арифметические операции, поэтому сначала необходимо привести значение к типу Дата с помощью функции Дата или ПолучитьДатуИзСтроки.

Еще одна ошибка связана с незнанием того, что 1С хранит дату с точностью до секунды. Если вы сравниваете даты на равенство после вычитания дня, но одна из дат имеет время 10:00:00, а другая 10:00:01, сравнение вернет Ложь. Для сравнения календарных дней всегда используйте функции НачалоДня или сравнивайте только составляющие даты (Год, Месяц, День).

Не рекомендуется "изобретать велосипед" и писать собственные функции для определения количества дней в месяце, если есть встроенные средства. Платформа 1С обновляется, и алгоритмы работы с календарем могут совершенствоваться. Использование стандартных функций ДобавлениеДаты гарантирует совместимость с будущими версиями платформы.

Также стоит быть осторожным при работе с нулевыми датами. В 1С существует "нулевая дата" (0001-01-01), и вычитание дней из неё может привести к ошибкам или некорректным значениям, если не предусмотрена проверка на допустимость результата. Всегда проверяйте дату на пустоту перед выполнением операций.

Соблюдение этих простых правил поможет сделать ваш код надежным и понятным для коллег. Помните, что работа со временем — это та область, где экономия на нескольких строках кода может стоить часов отладки в будущем.

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

Можно ли отнять день от даты в формате строки?

Нет, напрямую вычесть день из строки нельзя. Сначала необходимо преобразовать строку в тип Дата с помощью функции ПолучитьДатуИзСтроки или конструктора Дата(Год, Месяц, День), выполнить вычитание, и при необходимости обратно преобразовать результат в строку функцией Строка.

Как отнять один рабочий день, исключая выходные?

Стандартными средствами 1С отнять именно "рабочий" день нельзя, так как понятие выходного зависит от производственного календаря. Для этого нужно использовать цикл, в котором вы вычитаете по одному дню и проверяете день недели функцией ДеньНедели, пропуская субботу и воскресенье, пока не найдете нужный рабочий день.

Влияет ли вычитание дня на часовой пояс?

При использовании функции ДобавлениеДаты сдвиг происходит по астрономическому времени. Однако, если вы работаете в распределенной базе или веб-клиенте, отображение даты может зависеть от настроек часового пояса пользователя. Само значение в базе данных изменится корректно относительно UTC.

Что будет, если отнять день от пустой даты?

Попытка выполнить арифметическую операцию или вызвать функцию работы с датой для значения Неопределено или нулевой даты (в некоторых контекстах) приведет к ошибке выполнения или возврату некорректного значения. Всегда проверяйте переменную функцией ЗначениеЗаполнено перед вычислениями.

Как получить вчерашнюю дату в запросе без параметров?

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