How to parse a duration string into seconds with Javascript?

You can use optional substrings in the regex to match any combination as you describe:

/(\d+)\s*d(ays?)?\s*(\d+)\s*h(ours?)?\s*(\d+)\s*m(in(utes?)?)?/

This requires at least a d, h, and m but accepts common shortenings.


You can use this code to break your string into a number, followed by a unit string:

function getPieces(str) {
    var pieces = [];
    var re = /(\d+)[\s,]*([a-zA-Z]+)/g, matches;
    while (matches = re.exec(str)) {
        pieces.push(+matches[1]);
        pieces.push(matches[2]);
    }
    return(pieces);
}

Then function returns an array such as ["1","day","2","hours","3","minutes"] where alternating items in the array are the value and then the unit for that value.

So, for the string:

"1 day, 2 hours, 3 minutes"

the function returns:

[1, "day", 2, "hours", 3, "minutes"]

Then, you can just examine the units for each value to decide how to handle it.

Working demo and test cases here: http://jsfiddle.net/jfriend00/kT9qn/. The function is tolerant of variable amounts of whitespace and will take a comma, a space or neither between the digit and the unit label. It expects either a space or a comma (at least one) after the unit.


var str = "1 day, 2 hours, 3 minutes";

var seconds = 0;
str.replace (/\s*,?(\d+)\s*(?:(d)(?:ays?)?|(h)(?:ours?)?|(m)(?:in(?:utes?)?)?)/g, function (m0, n, d, h, m) {
  seconds += +n * (d ? 24 * 60 * 60 : h ? 60 * 60 : 60);
  return m0; 
});

Here I use replace not to change the string but to process the matches one by one. Note days, hours aminutes can be in any order.


Is the order of days/hours/minutes in your string guaranteed? If not, it may be easier to just do a separate RegEx for each. Something like this?

function getSeconds(str) {
  var seconds = 0;
  var days = str.match(/(\d+)\s*d/);
  var hours = str.match(/(\d+)\s*h/);
  var minutes = str.match(/(\d+)\s*m/);
  if (days) { seconds += parseInt(days[1])*86400; }
  if (hours) { seconds += parseInt(hours[1])*3600; }
  if (minutes) { seconds += parseInt(minutes[1])*60; }
  return seconds;
}