A library and webservice I am using communicates time-intervals in ISO 8601 format: PnYnMnDTnHnMnS. I want to convert such formats to seconds. And vice versa. Seconds are a
strtotime won't work with the ISO 8601 format directly (eg. P1Y1DT1S), but the format that it does understand (1Year1Day1Second) is not too far off -- it would a pretty straight-forward conversion. (a little "hacky"... but that's PHP for you).
Thanks Lee, I was not aware strtotime accepted this format. This was the missing part of my puzzle. Perhaps my functions can complete your answer.
function parse_duration($iso_duration, $allow_negative = true){
// Parse duration parts
$matches = array();
preg_match('/^(-|)?P([0-9]+Y|)?([0-9]+M|)?([0-9]+D|)?T?([0-9]+H|)?([0-9]+M|)?([0-9]+S|)?$/', $iso_duration, $matches);
if(!empty($matches)){
// Strip all but digits and -
foreach($matches as &$match){
$match = preg_replace('/((?!([0-9]|-)).)*/', '', $match);
}
// Fetch min/plus symbol
$result['symbol'] = ($matches[1] == '-') ? $matches[1] : '+'; // May be needed for actions outside this function.
// Fetch duration parts
$m = ($allow_negative) ? $matches[1] : '';
$result['year'] = intval($m.$matches[2]);
$result['month'] = intval($m.$matches[3]);
$result['day'] = intval($m.$matches[4]);
$result['hour'] = intval($m.$matches[5]);
$result['minute'] = intval($m.$matches[6]);
$result['second'] = intval($m.$matches[7]);
return $result;
}
else{
return false;
}
}
The function also supports negative formats. -P10Y9MT7M5S will return an array like: [year] => -10 [month] => -9 [day] => 0 [hour] => 0 [minute] => -7 [second] => -5 If this behaviour is not desired pass false as second parameter. This way the function will always return positive values. The min/plus symbol will still be available in result key ['symbol'].
And a little update: This function uses the first function to get the total amount of seconds.
function get_duration_seconds($iso_duration){
// Get duration parts
$duration = parse_duration($iso_duration, false);
if($duration){
extract($duration);
$dparam = $symbol; // plus/min symbol
$dparam .= (!empty($year)) ? $year . 'Year' : '';
$dparam .= (!empty($month)) ? $month . 'Month' : '';
$dparam .= (!empty($day)) ? $day . 'Day' : '';
$dparam .= (!empty($hour)) ? $hour . 'Hour' : '';
$dparam .= (!empty($minute)) ? $minute . 'Minute' : '';
$dparam .= (!empty($second)) ? $second . 'Second' : '';
$date = '19700101UTC';
return strtotime($date.$dparam) - strtotime($date);
}
else{
// Not a valid iso duration
return false;
}
}
$foo = '-P1DT1S';
echo get_duration_seconds($foo); // Output -86399
$bar = 'P1DT1S';
echo get_duration_seconds($bar); // Output 86401