Yandex Metrika
sanches.free 16 просмотров

Работа с датой в 1С‑Битрикс: форматы полей, DateTime и интервалы

Фильтрация по активности

Синтаксис $arFilter для границ показа (DATE_ACTIVE_FROM, DATE_ACTIVE_TO) описан вместе с операторами «между», «больше», «меньше» в материале про условия фильтрации выборок по датам и интервалам. Здесь — про разбор строк после выборки.

Какие строки приходят из элемента

У элемента инфоблока по умолчанию доступны в том числе поля без времени и с меткой времени. Разница в том, нужна ли вам только календарная дата создания или точный момент для сортировок и SLA.

  • CREATED_DATE — дата без времени (Y.m.d, как задаёт платформа).
  • DATE_CREATE — дата и время (d.m.Y H:i:s).
  • Свойство типа «дата/время» в выборках обычно приходит в пользовательских ключах вроде PROPERTY_*_VALUE; конкретный формат сохранённой строки проверьте на своей редакции после первого сохранения в админке или импорте.
$createdCalendar = DateTime::createFromFormat('Y.m.d', $row['CREATED_DATE']);
$createdMoment = DateTime::createFromFormat(
    'd.m.Y H:i:s',
    $row['DATE_CREATE'],
    new DateTimeZone(date_default_timezone_get())
);

$publishedAt = DateTime::createFromFormat(
    'd.m.Y H:i:s',
    $row['PROPERTY_EVENT_START_VALUE'],
    new DateTimeZone(date_default_timezone_get())
);

Если платформа сохранила свойство в другом представлении, скорректируйте шаблон createFromFormat; проще один раз вывести сырое значение на тестовом элементе, чем угадывать.

Сколько дней между двумя моментами

Разница в «целых днях» удобна для бейджей «осталось N дней»: $later->diff($earlier)->format('%a') даёт календарные сутки по правилам DateInterval, а не 24‑часовые скользящие интервалы. Округление вниз: разница 23 ч 59 м 59 с с тем же календарным днём считается нулём дней между датами; «не менее одних суток» для произвольной пары часов проверяйте по временной шкале.

Строка сохранена в базе во временной зоне сайта или в UTC — а new DateTime('now') живёт в зоне по умолчанию PHP. Если минуты только что созданной записи и «сейчас» оказываются в разных зонах, разница в днях или часах может быть неожиданной: при явных расчётах задаёте зону вторым аргументом или нормализуете метки времени перед сравнением.

$eventAt = DateTime::createFromFormat(
    'd.m.Y H:i:s',
    $row['PROPERTY_EVENT_START_VALUE'],
    new DateTimeZone('Europe/Moscow')
);
$now = new DateTime('now', new DateTimeZone('Europe/Moscow'));

$calendarDaysApart = (int) $eventAt->diff($now)->format('%a');
//$calendarDaysApart — см. ограничения DateInterval про неполные сутки

$biasSeconds = $now->getTimestamp() - $eventAt->getTimestamp();

Дробная разбивка «годы‑месяцы‑дни» из DateInterval выводится кодами %y, %m, %d, %h, %i, %s; официально это не «sprintf от Unix‑времени», а свой формат см. документацию PHP для DateInterval::format().

Опорная точка «полночь N дней назад»

Для окна статистики «с начала вчерашнего дня включительно» удобно отмотать календарь и обнулить компонент времени.

$numDaysBack = 1;
$todayMidnight = (new DateTime('today'));
$intervalStart = (clone $todayMidnight)
    ->modify(sprintf('- %d day', $numDaysBack))
    ->setTime(0, 0, 0);

Первый день месяца и квартала

Ниже — прямолинейный способ от текущей даты получить полуночь начала месяца и начала текущего квартала без подключения внешних календарных библиотек. Логика та же, что в одноимённых наглядных примерах: сначала «подрезать» число до первого дня месяца, затем откатить на остаток месяцев внутри квартала.

$cursor = new DateTime('today');
$dayOfMonth = (int) $cursor->format('j');
$monthIndex = (int) $cursor->format('n');

if ($dayOfMonth > 1) {
    $cursor->modify(sprintf('-%d day', $dayOfMonth - 1));
}
$monthStart = clone $cursor;

$quarterOffset = ($monthIndex - 1) % 3;
$quarterStart = (clone $monthStart)->modify(sprintf('-%d month', $quarterOffset));

Итого

  • Сверяйте шаблон ввода с реально сохранённым значением для каждого поля и свойства.
  • Для «ровно N календарных дней» используйте DateInterval, для честной физической задержки по шкале — разницу таймштампов.
  • Часовой пояс задавайте явно, если отчёты и выборка живут в разных правилах.
  • Фильтры по границам активности оставьте в отдельной шпаргалке по выборкам.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии