I'm currently trying to parse some user input into some regex groups so I can put the following inputs into the outputs.
The current regex I have is
^[0-9]+[d,D,h,H,m,M]$
This successfully matches a single date, for example 1d or 2h. However, I need it to dynamically work for every single one, even if some are not provided by the user.
input: "5d"
output: {days: 5, hours: 0, minutes: 0}
input: "1d 2h"
output: {days: 1, hours: 2, minutes: 0}
input: "1d 5h 2m"
output: {days: 1, hours: 5, minutes: 2}
input: "2m"
output: {days: 0, hours: 0, minutes: 2}
The output doesn't necessarily have to be in a js object, simply using regex groups would also be beneficial and something I could work with.
Any help would be very appreciated as I'm not sure what else to do.
You could expand your regex to include three named capture groups for the days, hours and minutes, then use the group values to populate an output object:
const parseInterval = s => {
let res = regex.exec(s) || {}
return {
days : +res.groups.days || 0,
hours : +res.groups.hours || 0,
minutes : +res.groups.minutes || 0
}
}
const input = [ "5d", "1D 2h", "1d 5H 2m", "2M"]
const regex = /(?:(?<days>\d+)d)?\s*(?:(?<hours>\d+)h)?\s*(?:(?<minutes>\d+)m)?/i
const result = input.map(parseInterval)
console.log(result)
You can use RegExp.exec() to get all global matches with a single regex:
function parseDate(input)
{
const reg = /([0-9]+)([dhm])(?=[0-9\s]|$)/gi,
result = {days: 0, hours: 0, minutes: 0},
map = {d: "days", h: "hours", m: "minutes"};
let match;
while((match = reg.exec(input.value)))
result[map[match[2]]] += +match[1]; //this will sum multiple matched values ie "1d 2d 3d" will become 6 days remove "+" from "+=" if this behaviour is not desired
console.clear();
console.log(result);
}
parseDate(dateInput);
<input id="dateInput" oninput="parseDate(this)" value="3d 2h 1m">
Here is a way if you can live with 3 regex to fill the object:
let input = [
'5d', // {days: 5, hours: 0, minutes: 0}
'1d 2h', // {days: 1, hours: 2, minutes: 0}
'1d 5h 2m', // {days: 1, hours: 5, minutes: 2}
'2m' // {days: 0, hours: 0, minutes: 2}
].forEach(str => {
let d = str.match(/\b([0-9]+)d\b/);
let h = str.match(/\b([0-9]+)h\b/);
let m = str.match(/\b([0-9]+)m\b/);
let obj = {
days: d ? Number(d[1]) : 0,
hours: h ? Number(h[1]) : 0,
minutes: m ? Number(m[1]) : 0,
}
console.log(str + ' => ' + JSON.stringify(obj));
});
Result:
5d => {"days":5,"hours":0,"minutes":0}
1d 2h => {"days":1,"hours":2,"minutes":0}
1d 5h 2m => {"days":1,"hours":5,"minutes":2}
2m => {"days":0,"hours":0,"minutes":2}