19

これを他の方法(この形式から変換)で行う方法を尋ねる質問はたくさんありますが、PHPでISO8601期間形式で出力する方法については何も見つかりません。

したがって、人間が読める形式の期間文字列のヒープがあります。HTML5マイクロデータの期間を印刷するために、それらをその場でISO8601形式に変換したいと思います。以下は、入ってくるいくつかの文字列のサンプルと、それらをフォーマットする方法です。

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

PHPのintervalオブジェクトに文字列をプッシュできます。

date_interval_create_from_date_string("1 hour 30 minutes");

しかし、ISO8601出力オプションがないようです

これにどのようにアプローチすればよいですか?

4

3 に答える 3

19

最初に数値に変換してから、それを処理します。

まず、使用しますstrtotime()

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

次に、それを継続時間解析し、PnYnMnDTnHnMnS形式で出力できます。私は次の方法を使用します(http://csl.sublevel3.org/php-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.org/1fHNlB6e

于 2012-11-09T02:56:19.807 に答える
12

これは、Ericのtime_to_iso8601_duration()関数の簡略化されたバージョンです。精度が低下することはなく(1年の概算365日)、約5倍高速です。このページによると、出力はそれほどきれいではありませんが、それでもISO8601と互換性があります。

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);
}
于 2016-11-23T10:08:34.870 に答える
3

もう1つのアプローチは、 DateIntervalオブジェクトに基づいて関数を作成することです。ISO8601期間形式は十分に説明されています。

このアプローチの利点は、関連する(現在の)表現のみを出力し、空の期間(通常は'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

于 2019-07-17T17:23:31.167 に答える