Формат DateInterval как ISO8601

В настоящее время я работаю над проектом php и мне нужно отформатировать DateInterval как ISO8601 (что-то вроде этого):

P5D

Этот формат можно использовать для создания объектов DateTime и DateInterval, но я не могу найти способ отформатировать DateInterval в этот формат. Есть ли? Если нет, что может быть легким решением для этого?

4

Решение

Хорошо, если вы посмотрите спецификацию для формата при его создании:

Y лет

М месяцев

D дней

W недель. Они преобразуются в дни, поэтому не могут быть объединены с D.

Ч часов

М минут

S секунд

Тогда посмотри, с чем надо работать (http://php.net/manual/en/dateinterval.format.php), похоже, что вы бы сделали:

$dateInterval = new DateInterval( /* whatever */ );
$format = $dateInterval->format("P%yY%mM%dD%hH%iM%sS");
//P0Y0M5D0H0M0S
//now, we need to remove anything that is a zero, but make sure to not remove
//something like 10D or 20D
$format = str_replace(["M0S", "H0M", "D0H", "M0D", "Y0M", "P0Y"], ["M", "H", "D", "M", "Y0M", "P"], $format);
echo $format;
//P0M5D

Теперь, одна вещь, которую я сделал по-другому, это я всегда включите месяцы, даже если они равны 0. Причина в том, что minutes а также months оба представлены M — если мы всегда включаем месяц, то если есть минута, мы знаем, что это минуты. В противном случае мы должны сделать кучу логики, чтобы увидеть, нужно ли нам изменить P в PT так что он знает, что M в данном случае означает Minute,

Например:

// For 3 Months
new DateInterval("P3M");
// For 3 Minutes
new DateInterval("PT3M"));

Но вместо этого мы делаем:

// For 3 Months
new DateInterval("P3M");
// For 3 Minutes
new DateInterval("P0M3M"));
2

Другие решения

Что касается @dave, я повторно реализовал его решение таким образом, чтобы решить некоторые из проблем, в частности требование всегда оставлять поле месяца. От Статья в Википедии по ISO-8601, это не похоже на T Обозначение является необязательным, даже если оно полностью отсутствует в вышеупомянутой реализации. Внедряя его, мы можем решить большинство наших проблем и создать более чистый код:

function date_interval_iso_format(DateInterval $interval) {
list($date,$time) = explode("T",$interval->format("P%yY%mM%dDT%hH%iM%sS"));
// now, we need to remove anything that is a zero, but make sure to not remove
// something like 10D or 20D
$res =
str_replace([ 'M0D', 'Y0M', 'P0Y' ], [ 'M', 'Y', 'P' ], $date) .
rtrim(str_replace([ 'M0S', 'H0M', 'T0H'], [ 'M', 'H', 'T' ], "T$time"),"T");
if ($res == 'P') // edge case - if we remove everything, DateInterval will hate us later
return 'PT0S';
return $res;
}

Обратите внимание, что мы удаляем T, если он не нужен, поэтому теперь оба использования M работают нормально:

"P5M" == date_interval_iso_format(new DateInterval("P5M")); // => true
"PT5M" == date_interval_iso_format(new DateInterval("PT5M")); // => true
1

По вопросам рекламы [email protected]