Here's what I've tried from this question's's accepted answer
const timeString = '1h 30m 1s'
const milliseconds = timeString.match(/\d /g)
.reduce((acc, cur, idx) => acc cur * (Math.pow(60, (2 - idx))) * 1000, 0)
console.log(milliseconds)
// result: 5401000
// expected result: 5401000
But, here's my the problem, if I only put 1m
for instance, expected output should be 60000 milliseconds
const timeString = '1m'
const milliseconds = timeString.match(/\d /g)
.reduce((acc, cur, idx) => acc cur * (Math.pow(60, (2 - idx))) * 1000, 0)
console.log(milliseconds)
// result: 3600000
// expected result: 60000
It thinks that the first argument is an hour, then minute followed by second. No matter what I input. So when I put 1m, it thinks that it is an hour. It's a fixed h, m & s format and I am not able to interchange them.
The solution I want is that I should be able to interchange them parse h as hours, m for minutes, and s for seconds no matter what order and able to choose only h, m or s like
If I only output 1m, should output 1 minute only and so on
const timeString = '1m`
// should output 60000
const timeString = '2h 1s`
// should output 7201000
If I interchange them, it should still output the same result since s is a second and h is an hour
const timeString = '1s 2h`
// should output 7201000
const timeString = '1s`
// should output 1000
or interchange them however I want no matter what format I use, and should still output the desired result in milliseconds
const timeString = '1s 6h 2m`
// should output 21721000
CodePudding user response:
Split up the string (on spaces) and within the reducer determine what value to use, based on the value of the string (the 'hms' part). In that case you're not dependent on the order of hms and you're able to use 1, 2 or 3 values. Something like:
const toMilliSeconds = ts => ts.split(` `)
.reduce((acc, cur, i) => {
const num = parseInt(cur);
const [isHour, isMinute] = [cur.endsWith(`h`), cur.endsWith(`m`)];
return (num * (isHour ? 3600 : isMinute ? 60 : 1) * 1000) acc;
}, 0);
console.log(`1h 30m 1s = ${toMilliSeconds(`1h 30m 1s`)}ms`);
console.log(`30m 1s = ${toMilliSeconds(`30m 1s`)}ms`);
console.log(`15s = ${toMilliSeconds(`15s`)}ms`);
console.log(`1h = ${toMilliSeconds(`1h`)}ms`);
console.log(`1m = ${toMilliSeconds(`1m`)}ms`);
console.log(`1h 2s = ${toMilliSeconds(`1h 2s`)}ms`);
console.log(`2h 1s = ${toMilliSeconds(`2h 1s`)}ms`);
console.log(`1s 6h 2m = ${toMilliSeconds(`1s 6h 2m`)}ms`);
.as-console-wrapper {
max-height: 100% !important;
}
If you want to use the original reducer (from the cited answer), sorting the string may be an idea:
const toMS = ts =>
ts.split(` `)
.sort( (a, b) => a.slice(-1).localeCompare(b.slice(-1)) )
.join(``)
.match(/\d /g)
.reduce((acc, cur, idx) => acc cur * (Math.pow(60, (2 - idx))) * 1000, 0);
console.log(`1h 30m 1s = ${toMS(`1h 30m 1s`)}ms`);
console.log(`30m 1s = ${toMS(`30m 1s`)}ms`);
console.log(`15s = ${toMS(`15s`)}ms`);
console.log(`1h = ${toMS(`1h`)}ms`);
console.log(`1m = ${toMS(`1m`)}ms`);
console.log(`1h 2s = ${toMS(`1h 2s`)}ms`);
console.log(`2h 1s = ${toMS(`2h 1s`)}ms`);
console.log(`1s 6h 2m = ${toMS(`1s 6h 2m`)}ms`);
.as-console-wrapper {
max-height: 100% !important;
}