如何将字符串持续时间转换成ISO 8601持续时间格式?(例如:"30分钟 "转换成 "PT30M")

问题描述 投票:14回答:3

有很多问题问如何用另一种方式来做(转换为 这种格式),但我找不到任何关于如何在 PHP 中以 ISO 8601 持续时间格式输出的方法。

所以我有一大堆人类可读格式的持续时间字符串--我想把它们转换成 ISO 8601 格式,以便打印 HTML5 微数据的持续时间。下面是一些字符串的样本,以及它们应该如何格式化。

"1 hour 30 minutes" --> PT1H30M
"5 minutes" --> PT5M
"2 hours" --> PT2H

我可以在PHP中把字符串推送到一个区间对象中,但似乎没有ISO 8601输出选项。

date_interval_create_from_date_string("1 hour 30 minutes");

但似乎没有一个ISO 8601输出选项

我应该如何处理这个问题?

php duration iso8601 dateinterval
3个回答
14
投票

我先把它转换为一个数字,然后用它来工作。

首先,使用 strtotime():

$time = strtotime("1 hour 30 minutes", 0);

然后,你可以解析它的持续时间,并输出在 PnYnMnDTnHnMnS 格式。我会使用以下方法(灵感来自于 http:/csl.sublevel3.orgphp-secs-to-human-text。):

function time_to_iso8601_duration($time) {
    $units = array(
        "Y" => 365*24*3600,
        "D" =>     24*3600,
        "H" =>        3600,
        "M" =>          60,
        "S" =>           1,
    );

    $str = "P";
    $istime = false;

    foreach ($units as $unitName => &$unit) {
        $quot  = intval($time / $unit);
        $time -= $quot * $unit;
        $unit  = $quot;
        if ($unit > 0) {
            if (!$istime && in_array($unitName, array("H", "M", "S"))) { // There may be a better way to do this
                $str .= "T";
                $istime = true;
            }
            $str .= strval($unit) . $unitName;
        }
    }

    return $str;
}

结果是: http:/codepad.org1fHNlB6e


8
投票

以下是Eric的简化版 time_to_iso8601_duration() 的功能。它的精度并没有下降(365天近似一年),而且速度快5倍左右。输出的数据虽然不那么漂亮,但仍然符合ISO 8601的要求,按照 这个 页。

function iso8601_duration($seconds)
{
    $days = floor($seconds / 86400);
    $seconds = $seconds % 86400;

    $hours = floor($seconds / 3600);
    $seconds = $seconds % 3600;

    $minutes = floor($seconds / 60);
    $seconds = $seconds % 60;

    return sprintf('P%dDT%dH%dM%dS', $days, $hours, $minutes, $seconds);
}

1
投票

另一种方法是根据 日期间隔 对象。该 ISO 8601期限格式 得到了很好的描述。

这种方法的优点是它只输出相关的(当前)表征,而且它支持空持续时间(通常表示为 'PT0S''P0D').

function dateIntervalToISO860Duration(\DateInterval $d) {
    $duration = 'P';
    if (!empty($d->y)) {
        $duration .= "{$d->y}Y";
    }
    if (!empty($d->m)) {
        $duration .= "{$d->m}M";
    }
    if (!empty($d->d)) {
        $duration .= "{$d->d}D";
    }
    if (!empty($d->h) || !empty($d->i) || !empty($d->s)) {
        $duration .= 'T';
        if (!empty($d->h)) {
            $duration .= "{$d->h}H";
        }
        if (!empty($d->i)) {
            $duration .= "{$d->i}M";
        }
        if (!empty($d->s)) {
            $duration .= "{$d->s}S";
        }
    }
    if ($duration === 'P') {
        $duration = 'PT0S'; // Empty duration (zero seconds)
    }
    return $duration;
}

一个例子。

echo dateIntervalToISO860Duration(
    date_diff(
        new DateTime('2017-01-25 18:30:22'), 
        new DateTime('2019-03-11 07:12:17')
    )
);

输出: P2Y1M13DT12H41M55S

© www.soinside.com 2019 - 2024. All rights reserved.