I\'m trying to parse a user input string for duration (into seconds) with Javascript.
Here are some example inputs that I\'d like to be able to deal with:
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;
}
A more general version of the accepted answer that accepts months and seconds as well.
const getSeconds = str => {
let seconds = 0;
let months = str.match(/(\d+)\s*M/);
let days = str.match(/(\d+)\s*D/);
let hours = str.match(/(\d+)\s*h/);
let minutes = str.match(/(\d+)\s*m/);
let secs = str.match(/(\d+)\s*s/);
if (months) { seconds += parseInt(months[1])*86400*30; }
if (days) { seconds += parseInt(days[1])*86400; }
if (hours) { seconds += parseInt(hours[1])*3600; }
if (minutes) { seconds += parseInt(minutes[1])*60; }
if (secs) { seconds += parseInt(secs[1]); }
return seconds;
};
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.
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.
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.