Saturday, 18 October 2014

Twig filter to convert duration in minutes to ISO 8601 formatted duration string

I was gonna write this myself but instead borrowed heavily (stole shamelessly) from Eric's answer on stackoverflow. Once it's registered with $twig then simply call it like this:

datetime="{{ session.duration|minutes_to_iso8601_duration }}"

And you'll have a nicely acceptable datetime attribute for your HTML durations... if that's your thing that is ;-).

$filter = new Twig_SimpleFilter('minutes_to_iso8601_duration', function ($minutes) {
    $time = strtotime($minutes . "minutes", 0);
    $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"))) { 
                $str .= "T";
                $istime = true;
            }
            $str .= strval($unit) . $unitName;
        }
    }
    return $str;
});

If you need to update the value on screen then I use Moment.js like this:

$("#session_duration").attr("datetime", moment.duration(parseInt(data.duration, 10), "minutes").toISOString());

I'm not sure why it was so important for me to have this but I'm very glad I've got valid HTML5 pages now! The standard is interesting as well!