#php #dateinterval
#php #dateinterval
Вопрос:
Ситуация / проблема
У меня проблема с DateInterval в PHP.
Учитывая следующий код
$interval = new DateInterval("PT6000S");
echo $interval->h; // 0
echo $interval->i; // 0
echo $interval->s; // 6000
echo $interval->format("%h:%i"); // 0:0
Я хочу, чтобы это представляло 1 час и 40 минут, а не 6000 секунд.
Вопрос
Есть ли встроенный способ нормализовать DateInterval? Конкретный способ записи duration
строки? Или это то, что должно быть сделано нормально?
Я могу изменить способ его создания и форматирования, если у кого-нибудь есть «обходной путь», чтобы предложить.
Я провел свое исследование, но, как ни странно, я не нашел ничего полезного в этой проблеме.
Ответ №1:
Класс DateInterval немного раздражает подобным образом. Строго говоря, это правильно, поскольку в вашей строке спецификации интервала указано ноль минут и часов, но определенно не помогает, что она не переносит лишние секунды в минуты и часы.
Один из вариантов, который я использовал ранее, — добавить интервал к новому объекту DateTime, инициализированному эпохой Unix, а затем отформатировать полученное время вместо этого. Это означало бы использование строк стандартного формата даты (so h
вместо %h
и т.д.)
echo (new DateTime('@0'))->add(new DateInterval("PT6000S"))->format('h:i');
// 01:40
Смотрите https://3v4l.org/OX6JF
Комментарии:
1. Это решение ограничено временем до 24 часов. Если количество секунд больше, результаты будут неверными. Попробуйте 3v4l.org/XLKfTL
Ответ №2:
Решение
Как и каждый раз, когда я прошу о помощи, я не могу прекратить попытки, и я обычно нахожу ответ сразу после. На этот раз никаких исключений.
Я нашел заметку пользователя в документации DateInterval.
Вы должны создать два DateTime
(они могут быть любыми датой и временем), добавить свой интервал ко второму и вычесть первый из второго. Это позволит заполнить DateInterval нормализованным способом.
Вот код, написанный пользователем, завернутый в удобную функцию:
public function createDateInterval(string $duration): DateInterval
{
$d1 = new DateTime();
$d2 = new DateTime();
$d2->add(new DateInterval($duration));
return $d2->diff($d1);
}
(Обратите внимание, что эта функция может выдать исключение, если ваша $duration
строка неправильно отформатирована.)
Ответ №3:
Это решение использует DateTime с фиксированным временем. Почему?
DateTime также поддерживает микросекунды. Поэтому существует определенная вероятность того, что 2 вызова new Date() не вернут одно и то же время. Тогда мы можем получить неправильные результаты.
//360000 Sec = 100 hours = 4 Days 4 hours
$di = new DateInterval("PT360000S");
$diNormalize = date_create('@0')->diff(date_create('@0')->add($di));
var_export($diNormalize);
/*
DateInterval::__set_state(array(
'y' => 0,
'm' => 0,
'd' => 4,
'h' => 4,
'i' => 0,
's' => 0,
'f' => 0.0,
'weekday' => 0,
'weekday_behavior' => 0,
'first_last_day_of' => 0,
'invert' => 0,
'days' => 4,
'special_type' => 0,
'special_amount' => 0,
'have_weekday_relative' => 0,
'have_special_relative' => 0,
))
*/
echo $diNormalize->format('%a days %h hours %i minutes');
//4 days 4 hours 0 minutes
DateInterval имеет специальный метод format для вывода. Это следует использовать здесь, и не следует использовать обходные пути через date, gmdate или DateTime.