В настоящее время я работаю над проектом php и мне нужно отформатировать DateInterval как ISO8601 (что-то вроде этого):
P5D
Этот формат можно использовать для создания объектов DateTime и DateInterval, но я не могу найти способ отформатировать DateInterval в этот формат. Есть ли? Если нет, что может быть легким решением для этого?
Хорошо, если вы посмотрите спецификацию для формата при его создании:
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"));
Что касается @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