I'm trying to convert ISO 8601 string to seconds in JS/Node. The best I could come up with was:
function convert_time(duration) {
var a = duration.match(/\d+/g)
var duration = 0
if(a.length == 3) {
duration = duration + parseInt(a[0]) * 3600;
duration = duration + parseInt(a[1]) * 60;
duration = duration + parseInt(a[2]);
}
if(a.length == 2) {
duration = duration + parseInt(a[0]) * 60;
duration = duration + parseInt(a[1]);
}
if(a.length == 1) {
duration = duration + parseInt(a[0]);
}
return duration
}
It works when I input strings such as "PT48S", "PT3M20S" or "PT3H2M31S", but fails miserably if the string is "PT1H11S". Does anyone have a better idea?
If you're using moment.js you can simply call...
moment.duration('PT15M33S').asMilliseconds();
= 933000 ms
EDIT 2021: While this works, and still gets upvotes, I wouldn't advise including moment.js just for this. I'd recommend using a regex answer like @redgetan's
function YTDurationToSeconds(duration) {
var match = duration.match(/PT(\d+H)?(\d+M)?(\d+S)?/);
match = match.slice(1).map(function(x) {
if (x != null) {
return x.replace(/\D/, '');
}
});
var hours = (parseInt(match[0]) || 0);
var minutes = (parseInt(match[1]) || 0);
var seconds = (parseInt(match[2]) || 0);
return hours * 3600 + minutes * 60 + seconds;
}
works for these cases:
PT1H
PT23M
PT45S
PT1H23M
PT1H45S
PT23M45S
PT1H23M45S
I suggest this little hack to prevent your problematic case:
function convert_time(duration) {
var a = duration.match(/\d+/g);
if (duration.indexOf('M') >= 0 && duration.indexOf('H') == -1 && duration.indexOf('S') == -1) {
a = [0, a[0], 0];
}
if (duration.indexOf('H') >= 0 && duration.indexOf('M') == -1) {
a = [a[0], 0, a[1]];
}
if (duration.indexOf('H') >= 0 && duration.indexOf('M') == -1 && duration.indexOf('S') == -1) {
a = [a[0], 0, 0];
}
duration = 0;
if (a.length == 3) {
duration = duration + parseInt(a[0]) * 3600;
duration = duration + parseInt(a[1]) * 60;
duration = duration + parseInt(a[2]);
}
if (a.length == 2) {
duration = duration + parseInt(a[0]) * 60;
duration = duration + parseInt(a[1]);
}
if (a.length == 1) {
duration = duration + parseInt(a[0]);
}
return duration
}
Fiddle
Here's my solution:
function parseDuration(duration) {
var matches = duration.match(/[0-9]+[HMS]/g);
var seconds = 0;
matches.forEach(function (part) {
var unit = part.charAt(part.length-1);
var amount = parseInt(part.slice(0,-1));
switch (unit) {
case 'H':
seconds += amount*60*60;
break;
case 'M':
seconds += amount*60;
break;
case 'S':
seconds += amount;
break;
default:
// noop
}
});
return seconds;
}
You can find a very simple PHP solution here - How To Convert Youtube API Time (ISO 8601 String Video Duration) to Seconds In PHP - Code
This function convert_time() takes one parameter as input - the Youtube API Time (Video Duration) which is in ISO 8601 string format and returns its duration in seconds.
function convert_time($str)
{
$n = strlen($str);
$ans = 0;
$curr = 0;
for($i=0; $i<$n; $i++)
{
if($str[$i] == 'P' || $str[$i] == 'T')
{
}
else if($str[$i] == 'H')
{
$ans = $ans + 3600*$curr;
$curr = 0;
}
else if($str[$i] == 'M')
{
$ans = $ans + 60*$curr;
$curr = 0;
}
else if($str[$i] == 'S')
{
$ans = $ans + $curr;
$curr = 0;
}
else
{
$curr = 10*$curr + $str[$i];
}
}
return($ans);
}
Testing Some Inputs:
"PT2M23S" => 143
"PT2M" => 120
"PT28S" => 28
"PT5H22M31S" => 19351
"PT3H" => 10800
"PT1H6M" => 3660
"PT1H6S" => 3606
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With