Дата. Работа с датой в Битрикс D7

Дата выведется без времени создания и с правильным окончанием месяца, если это указано в настройках конкретного сайта

$dateCreate = CIBlockFormatProperties::DateFormat(
        'j F Y', 
        MakeTimeStamp(
            $arItem["DATE_CREATE"], 
            CSite::GetDateFormat()
        )
);
echo $dateCreate;

Сконвертировать в формате сайта

echo FormatDateFromDB($arItem["DATE_CREATE"], 'SHORT');

Если нужно вывести дату и время создания

$dateCreate = CIBlockFormatProperties::DateFormat(
        'j F Y h:m', 
        MakeTimeStamp(
            $arItem["DATE_CREATE"], 
            CSite::GetDateFormat()
        )
);
echo $dateCreate;

Если нужно отделить дату и время друг от друга, что бы как-то красиво сверстать.

$dateCreate = CIBlockFormatProperties::DateFormat(
        'j F Y / h:m', 
        MakeTimeStamp(
            $arItem["DATE_CREATE"], 
            CSite::GetDateFormat()
        )
);
$arDateCreate = explode('/', $dateCreate);
echo $arDateCreate['0']; // Сама по себе дата
echo $arDateCreate['1']; // Само по себе время

РАБОТА С ДАТОЙ И ВРЕМЕНЕМ В БИТРИКС D7

Большинство дат в ORM D7 являются объектами класса Bitrix\Main\Type\DateTime. Для сокращения используем:

use Bitrix\Main\Type\DateTime;

Объект Datetime является практически аналогом встроенного в PHP класса \DateTime, но от него не наследуется.

Объект Битрикс-класса можно получить из объекта PHP-класса с помощью метода createFromPhp или из timestamp с помощью createFromTimestamp:

$objDateTime = DateTime::createFromPhp(new \DateTime('2000-01-01'));

$objDateTime = DateTime::createFromTimestamp(1346506620);

Также есть конструкторы:

// Текущее время:
$objDateTime = new DateTime();
// Из строки в формате текущего сайта
$objDateTime = new DateTime("25.12.2012 12:30:00");
// Из строки с указанием формата:
$objDateTime = new DateTime("2007-05-14 12:10:00", "Y-m-d H:i:s");

Из объекта можно получить представление в виде timestamp:

echo $objDateTime->getTimestamp();

в виде строки в формате текущего сайта:

echo $objDateTime->toString();

в произвольном формате (фактически обёртка над DateTime::format):

echo $objDateTime->format("Y-m-d H:i:s");

Метод add реализует сложение и вычитание дат, можно указывать смещение словами years, months, days, weeks, hours, minutes, seconds и знаками +/-:

$objDateTime = new DateTime("01.01.2012 00:00:00"); // "2012-01-01 00:00:00"
$objDateTime->add("1 day"); // "2012-01-01 00:00:00" => "2012-01-02 00:00:00"
$objDateTime->add("-1 day"); // "2012-01-01 00:00:00" =>"2011-12-31 00:00:00"
$objDateTime->add("3 months - 5 days + 10 minutes"); // "2012-01-01 00:00:00" =>"2012-03-27 00:10:00"

Метод add изменяет объект, здесь для наглядности приведены результаты вызова add с начального состояния \$objDateTime.

Также в add можно указывать смещение в формате DateInterval (но буква P в начале строки необязательна):

$objDateTime = new DateTime("01.01.2012 00:00:00"); // "2012-01-01 00:00:00"
$objDateTime->add("7M5DT2M"); // "2012-01-01 00:00:00" =>"2012-08-06 00:02:00"
$objDateTime->add("-2YT10M"); // "2012-01-01 00:00:00" =>"2009-12-31 23:50:00"

При указании смещения следует указывать периоды, от большей единицы до меньшей (например, года, месяцы, часы).



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

Для $arFilter использовать DATE_ACTIVE_FROM, DATE_ACTIVE_TO

Приведение даты в PHP-формат

Элементы имеют следующие параметры:

  • CREATED_DATE - дата создания БЕЗ учета времени

  • DATE_CREATE - дата создания с учетом времени

$date = DateTime::createFromFormat('Y.m.d', $item['CREATED_DATE']); // только дата
$date = DateTime::createFromFormat('d.m.Y H:i:s', $item['DATE_CREATE']); // дата и время

Для свойств:

$date = DateTime::createFromFormat('d.m.Y H:i:s', $item['PROPERTY_SOME_DATE_VALUE']);

Разница в днях между датами

Разница в днях между датой элемента и текущей датой:

$date = DateTime::createFromFormat('d.m.Y H:i:s', $item['PROPERTY_SOME_DATE_VALUE']);
$now = new DateTime();
$dayDiff = $date->diff($now)->format('%a');

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

Округление идет в меньшую сторону, т.е. разница в 23 часа 59 мин 59 сек = 0 дней. Можно сказать, что если $date->diff($now)->format('%a') >= 1, прошло минимум 24 часа.

Точное значение в годах, месяцах, днях, часах, минутах и секундах:

die(var_dump(
  $date->diff($now)->format('%Y-%M-%D %H:%I:%S')
));

Разница в секундах - именно не по секундам, а общая в секундах:

$diff = $now->getTimestamp() - $date->getTimestamp();

Отмотать дату

Отмотать дату на начало предыдущего дня ($numDays = 1) или позавчера ($numDays = 2), причем с округлением до полуночи:

$now = new DateTime('now');
$intervalStart = clone $now;
$intervalStart->modify(sprintf('-%s day', $numDays))->setTime(0, 0, 0); // 2016-05-04 00:00:00

Начало месяца и начало квартала

Дата начала месяца и квартала для текущей даты.

$monthDate = new DateTime(); // текущая дата
$curDay = $monthDate->format('j');
$curMonth = $monthDate->format('n');
$curQuarter = ceil($curMonth / 3); // номер текущего квартала
$quarterDeltaMonth = ($curMonth - 1) % 3;

if($curDay != 1) {
  $monthDate->modify(sprintf('-%d day', $curDay - 1)); // начало месяца
}
$quarterDate = clone $monthDate;
$quarterDate->modify(sprintf('-%d month', $quarterDeltaMonth)); // начало квартала

Разница между датами в днях\часах\минутах

function dateDiff($date1, $date2): array
{
    // Используем PHP классы для работы с датой.
    $time = new \DateTime($date1);
    $since_time = $time->diff( new \DateTime($date2) );

    Bitrix\Main\Diag\Debug::writeToFile($since_time->days, date('Y-m-d').' demo_key', 'demo_key_HL.log');

    $result['days'] = $since_time->days;
    $result['hours'] = $since_time->days * 24 + $since_time->h;
    $result['minutes'] = ($since_time->days * 24 * 60) + ($since_time->h * 60) + $since_time->i;

    return $result;
}

// Функция выше, при условии, что date1 больше date2 (т.е. дата, которую сравниваем уже прошла), все равно вернет разницу положительным числом. Если нужно // не позволять опускаться ниже date1 добавляем проверку.

function dateDiff($date1, $date2): false | int
{
    // Используем PHP классы для работы с датой.
    $date1 = new \DateTime($date1);
    $date2 = new \DateTime($date2);
    if ($date1 > $date2) {
        return 0;
    }

    return $date1->diff($date2)->days;
}

Конвертируем timestamp в привычный формат

function timestampToDate($timestamp,$format = "d.m.Y H:i:s"){
    return date($format, $timestamp);
}

Вычитаем\прибавляем к дате месяц\день и т.д.

function dateDecrementByMonth($date_start){//Вычитаем из даты месяц
    return date("d-m-Y", strtotime("-1 month", strtotime($date_start)));
}  

function dateIncrementByMonth($date_start){//Прибавляем к дате месяц
    return date("d-m-Y", strtotime("+1 month", strtotime($date_start)));
}

Парсим объект даты\времени на составляющие

$datetime = "21.01.2004 23:44:15"; //Исходное время
$format = "DD.MM.YYYY HH:MI:SS"; //Формат

if ($arr = ParseDateTime($datetime, $format))
{
    echo "День:    ".$arr["DD"]; // День: 21
    echo "Месяц:   ".$arr["MM"]; // Месяц: 1
    echo "Год:     ".$arr["YYYY"]; // Год: 2004
    echo "Часы:    ".$arr["HH"]; // Часы: 23
    echo "Минуты:  ".$arr["MI"]; // Минуты: 44
    echo "Секунды: ".$arr["SS"]; // Секунды: 15
}

Памятка по принятым стандартам формата даты в разных странах

Россия              DD.MM.YYYY  HH:MI:SS
США             MM-DD-YYYY  HH:MI:SS
Международный английский    DD-MM-YYYY  HH:MI:SS
Великобритания          DD/MM/YYYY  HH:MI:SS