Reputation: 363
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.
Upvotes: 2
Views: 174
Reputation: 147156
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)
Upvotes: 3
Reputation: 10201
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">
Upvotes: 3
Reputation: 7616
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}
Upvotes: 2
Reputation: 81
you can use a function like this
const myfun = (s) => {
const days = s.match(/[0-9]+[d,D]/) ? s.match(/[0-9]+[d,D]/)[0] : "0d"
const hours = s.match(/[0-9]+[h,H]/) ? s.match(/[0-9]+[h,H]/)[0] : "0d"
const minutes = s.match(/[0-9]+[m,M]/) ? s.match(/[0-9]+[m,M]/)[0] : "0d"
return {
days: days.slice(0, -1),
hours: hours.slice(0, -1),
minutes:minutes.slice(0, -1)
}
}
console.log(myfun("5d")) // {days: 5, hours: 0, minutes: 0}
console.log(myfun("1d 2h")) // { days: '1', hours: '2', minutes: '0' }
console.log(myfun("1d 5h 2m")) // { days: '1', hours: '5', minutes: '2' }
console.log(myfun("2m")) // { days: '0', hours: '0', minutes: '2' }
console.log(myfun("randomString")) // { days: '0', hours: '0', minutes: '0' }
Upvotes: 1