Мы, как программисты 1С, постоянно сталкиваемся с необходимостью выполнения различных операций над датами и временем. Часто перед нами стоит задача рассчитать временные интервалы, добавить определенное количество дней или часов к дате, или вычислить разницу между двумя датами. При выполнении этих операций, многие из нас сталкиваются с повторяющимся в коде выражением 24 * 60 * 60, которое используется для обозначения количества секунд в сутках. Рассмотрим, почему такой подход становится привычным, какие потенциальные проблемы он может создавать и какие более эффективные, читаемые и поддерживаемые альтернативы предлагает платформа 1С.
Выражение 24 * 60 * 60 для многих разработчиков является интуитивно понятным способом представления количества секунд в сутках. Оно явно показывает, что мы умножаем 24 часа на 60 минут, а затем на 60 секунд, чтобы получить общее число секунд. Этот подход имеет свои преимущества, но также и существенные недостатки.
Давайте рассмотрим, почему разработчики часто выбирают именно такой способ записи:
24 * 60 * 60 сразу же раскрывает свою суть, не требуя дополнительных комментариев или знания "магического числа" 86400. Даже новый разработчик, впервые столкнувшийся с кодом, с легкостью поймет, что здесь рассчитывается длительность суток в секундах.
23 * 50 * 50 для гипотетических марсианских суток) будет более наглядным и интуитивно понятным.
86400. Это потенциально снижает количество опечаток.
Рассмотрим типовые примеры из кода 1С, где встречается такое выражение:
// Добавление одного дня к дате путем прибавления секунд
ТекДата = ТекущаяДата();
ДатаЧерезОдинДень = ТекДата + 24 * 60 * 60;
Сообщить("Дата через один день: " + ДатаЧерезОдинДень);
Или при определении интервалов в списках выбора:
СписокИнтервалов = Новый СписокЗначений();
СписокИнтервалов.Добавить(1 * 24 * 60 * 60, "1 день");
СписокИнтервалов.Добавить(1 * 7 * 24 * 60 * 60, "1 неделя");
Несмотря на кажущуюся очевидность и удобство, многократное повторение выражения 24 * 60 * 60 по всему коду может создать ряд проблем для поддерживаемости и чистоты кода:
24 * 60 * 60 не сделает его существенно более читаемым или понятным.
86400), и разницы в производительности практически нет, сама концепция использования сложных выражений там, где можно использовать простое число или константу, может быть спорной.
Мы выясним, какие существуют более "чистые", эффективные и поддерживаемые способы работы с датами и временными интервалами в 1С:Предприятие.
Самым рекомендуемым и наиболее правильным подходом для манипуляций с датами в 1С является использование встроенной функции ДобавитьКДате(). Эта функция специально разработана для этих целей и берет на себя все сложности, связанные с переходом через границы месяцев, годов, а также учетом високосных лет и даже високосных секунд на уровне платформы.
Преимущества использования ДобавитьКДате():
ВидДаты.День, ВидДаты.Час, ВидДаты.Минута, ВидДаты.Секунда) и в каком количестве хотим добавить.
Рассмотрим, как использовать ДобавитьКДате() вместо ручных расчетов или постоянного прибавления секунд:
// Добавляем один день к текущей дате
ТекДата = ТекущаяДата();
ДатаЧерезОдинДень = ДобавитьКДате(ТекДата, ВидДаты.День, 1);
Сообщить("Дата через один день: " + ДатаЧерезОдинДень); // Пример: 2023.10.26 12:00:00 -> 2023.10.27 12:00:00
// Добавляем 5 часов к дате
ДатаЧерезПятьЧасов = ДобавитьКДате(ТекДата, ВидДаты.Час, 5);
Сообщить("Дата через пять часов: " + ДатаЧерезПятьЧасов);
// Добавляем 30 секунд к дате
ДатаЧерезТридцатьСекунд = ДобавитьКДате(ТекДата, ВидДаты.Секунда, 30);
Сообщить("Дата через тридцать секунд: " + ДатаЧерезТридцатьСекунд);
// Добавляем 7 дней (одна неделя)
ДатаЧерезНеделю = ДобавитьКДате(ТекДата, ВидДаты.День, 7);
Сообщить("Дата через неделю: " + ДатаЧерезНеделю);
// Пример использования для вычитания (отрицательное значение)
ДатаВчера = ДобавитьКДате(ТекДата, ВидДаты.День, -1);
Сообщить("Дата вчера: " + ДатаВчера);
Использование ДобавитьКДате() делает код более лаконичным, выразительным и устойчивым к возможным ошибкам.
Если все же по какой-то причине нам необходимо оперировать точным числовым значением количества секунд (например, для специфических расчетов длительности, взаимодействия с внешними системами, или в параметрах функций, требующих числового значения в секундах), более предпочтительно использовать именованные константы или переменные вместо "магического числа" 86400 или его развернутого выражения 24 * 60 * 60.
Преимущества именованных констант:
КоличествоСекундВСутках) сразу передает смысл числа, делая код более самодокументируемым.
Рассмотрим примеры использования именованных констант:
// В общем модуле (например, "ОбщегоНазначенияСервер")
// Можно объявить как экспортируемую переменную или функцию
// Для примера:
Перем мКоличествоСекундВСутках Экспорт = 86400;
// Или как функцию, если нужно инкапсулировать вычисление
Функция ПолучитьДлинуСутокВСекундах() Экспорт
Возврат 24 * 3600; // Или 86400
КонецФункции
// Использование в другом модуле:
ДлительностьДняВСекундах = ОбщегоНазначенияСервер.мКоличествоСекундВСутках;
ДатаПлюсОдинДень = ТекущаяДата() + ДлительностьДняВСекундах;
Сообщить("Дата плюс один день (через константу): " + ДатаПлюсОдинДень);
// Или через функцию:
ДлительностьДняВСекундахФункция = ОбщегоНазначенияСервер.ПолучитьДлинуСутокВСекундах();
ДатаПлюсОдинДеньФункция = ТекущаяДата() + ДлительностьДняВСекундахФункция;
Сообщить("Дата плюс один день (через функцию): " + ДатаПлюсОдинДеньФункция);
Некоторые разработчики предпочитают использовать число 86400 напрямую, считая его "общеизвестной" константой для опытных программистов, подобно числу Пи. В таком случае, для повышения читаемости и ясности, можно добавить комментарий:
// Использование "магического числа" с явным комментарием
ДатаПлюсОдинДень = ТекущаяДата() + 86400; // 86400 секунд в сутках
Как показывают примеры из Библиотеки стандартных подсистем (БСП) 1С, встречаются и более сложные конструкции, использующие 86400 для производных расчетов:
// Пример из типового кода 1С, демонстрирующий использование 86400
Если Шаг = "Час" Тогда
// Расчет количества секунд в часе на основе общего количества секунд в сутках
ШагЧисло = 86400 / 24;
КонецЕсли;
Это подчеркивает, что даже внутри типовых решений существуют различные подходы к выражению этих значений, но централизованное управление через константы или функции всегда более предпочтительно.
Для более сложных или часто используемых операций с датами, которые не полностью покрываются стандартной функцией ДобавитьКДате() или требуют специфической бизнес-логики, мы рекомендуем создавать собственные общие функции или даже целые модули по работе с датами. Это позволяет инкапсулировать сложную логику, сделать ее переиспользуемой и значительно облегчить поддержку кода.
Например, вы можете создать функцию, которая добавляет определенное количество дней к дате, но с какой-то специфической логикой, учитывающей выходные или праздничные дни:
// Пример функции в общем модуле "РаботаСДатами" (ОбщегоНазначенияКлиентСервер)
Функция ДобавитьДнейКДатеСУчетомРабочих(ДатаНачала, КоличествоРабочихДней) Экспорт
НоваяДата = ДатаНачала;
Для Индекс = 1 По КоличествоРабочихДней Цикл
НоваяДата = ДобавитьКДате(НоваяДата, ВидДаты.День, 1);
// Дополнительная логика, например, пропуск выходных
Пока ДеньНедели(НоваяДата) = 6 Или ДеньНедели(НоваяДата) = 7 Цикл // Суббота или воскресенье
НоваяДата = ДобавитьКДате(НоваяДата, ВидДаты.День, 1);
КонецЦикла;
КонецЦикла;
Возврат НоваяДата;
КонецФункции
// Другой пример - функция для получения длины суток в секундах,
// если это значение может быть динамическим или зависит от контекста
Функция ПолучитьДлинуСутокВСекундахДляРасчета() Экспорт
// Может быть сложная логика, учитывающая часовые пояса или другие факторы
Возврат 24 * 3600; // Или использовать именованную константу
КонецФункции
// Использование в коде:
ИсходнаяДата = ТекущаяДата();
// Добавляем 5 рабочих дней к текущей дате
НоваяДатаРабочая = РаботаСДатами.ДобавитьДнейКДатеСУчетомРабочих(ИсходнаяДата, 5);
Сообщить("Дата через 5 рабочих дней: " + НоваяДатаРабочая);
Такой подход делает ваш код более модульным, понятным, облегчает его тестирование и дальнейшую модификацию.
Как было предложено в обсуждении на форуме, существует также способ программно определить количество секунд в сутках. Этот метод может быть полезен в контекстах, где требуется быть максимально точным или учитывать потенциальные изменения (например, влияние "високосных секунд" или особенности перехода летнего/зимнего времени). Он позволяет получить фактическую длительность суток, как ее видит платформа 1С на данный момент.
// Расчет количества секунд между началом текущего и началом следующего дня
НачалоТекущегоДня = НачалоДня(ТекущаяДата());
НачалоСледующегоДня = НачалоДня(ДобавитьКДате(ТекущаяДата(), ВидДаты.День, 1));
ДлинаСутокВСекундах = НачалоСледующегоДня - НачалоТекущегоДня;
Сообщить("Длина суток в секундах (программно): " + ДлинаСутокВСекундах);
Этот метод является одним из самых "астрономически точных" для получения фактической продолжительности суток по системным часам и датам, с которыми оперирует 1С. Он фактически вычисляет интервал между двумя точками времени, а платформа 1С обычно учитывает любые корректировки времени (например, високосные секунды, если они произошли в этом интервале) при вычитании дат.
В ходе обсуждения был затронут важный и довольно глубокий вопрос о "високосных секундах" — дополнительных секундах, которые периодически добавляются к универсальному координированному времени (UTC) для синхронизации с фактическим вращением Земли. Этот вопрос напрямую связан с точностью значения 86400.
86400 секунд, а иногда 86401 (или очень редко 86399, если бы происходило ускорение вращения).
ДобавитьКДате() или программное вычитание дат (как в предыдущем разделе) является наиболее надежным способом, поскольку опирается на внутренние механизмы платформы, учитывающие фактическое системное время.
Для подавляющего большинства бизнес-приложений в 1С точность до високосной секунды не является критичной. Однако, если вы разрабатываете системы, где такая точность важна (например, для высокочастотного трейдинга, научных или измерительных расчетов), следует иметь это в виду и доверять встроенным функциям 1С или использовать программный расчет интервала.
Выбор между 24 * 60 * 60, 86400, именованной константой или использованием функции ДобавитьКДате() часто зависит от внутренних стандартов кодирования команды и личных предпочтений разработчика. Однако, мы рекомендуем придерживаться следующих принципов для написания чистого, надежного и поддерживаемого кода:
ДобавитьКДате(). Это самый чистый, надежный и читаемый способ, который корректно обрабатывает все календарные особенности.
Константа.КоличествоСекундВСутках или переменной в общем модуле), чтобы централизовать это значение и повысить читаемость кода.
Главное — обеспечить единообразие и понятность кода для всех, кто будет с ним работать, и использовать инструменты платформы 1С максимально эффективно, минимизируя повторения и потенциальные источники ошибок.