Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert string duration to ISO 8601 duration format? (e.g. "30 minutes" to "PT30M")

There are plenty of questions asking how to do this the other way (converting from this format), but I can't find anything on how to output in the ISO 8601 duration format in PHP.

So I have a heap of duration strings in human readable format - I want to convert them into the ISO 8601 format on the fly to print the durations for HTML5 microdata. Below is a sample of some of the strings coming in, and how they should be formatted

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

I can push the string into an interval object in PHP:

date_interval_create_from_date_string("1 hour 30 minutes");

but there doesn't seem to be a ISO 8601 output option

How should I approach this?

like image 566
Chris Avatar asked Nov 09 '12 02:11

Chris


People also ask

How do I specify the duration in an ISO 8601 format?

Briefly, the ISO 8601 notation consists of a P character, followed by years, months, weeks, and days, followed by a T character, followed by hours, minutes, and seconds with a decimal part, each with a single-letter suffix that indicates the unit. Any zero components may be omitted.

What does PT5M mean?

The format for this string is P<days>DT<hours>H<minutes>M<seconds>S (for example, "PT5M" is 5 minutes, "PT1H" is 1 hour, and "PT20M" is 20 minutes). The maximum time allowed is 31 days, and the minimum time allowed is 1 minute. syntax Copy.


1 Answers

I'd convert it to a number first, then work with that.

First, use strtotime():

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

Then you can parse it for duration, and output in PnYnMnDTnHnMnS format. I'd use the following method (inspired by 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;
}

The result: http://codepad.org/1fHNlB6e

like image 200
Cat Avatar answered Sep 16 '22 13:09

Cat