如何将人类时间字符串转换为毫秒?

How can I convert human time strings into milliseconds?

这是我从 接受的答案中尝试过的

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

但是,问题来了,如果我只输入 1m 例如,预期输出应该是 60000 毫秒

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

它认为第一个参数是一个小时,然后是分钟,然后是第二个。不管我输入什么。所以当我输入 1m 时,它认为是一个小时。这是固定的 h、m 和 s 格式,我无法互换它们。

我想要的解决方案是,我应该能够将它们互换,h 为小时,m 为分钟,s 为秒,无论顺序如何,并且只能选择 h、m 或 s 之类的

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 

拆分字符串(在空格上)并在缩减器中根据字符串的值('hms' 部分)确定要使用的值。在这种情况下,您不依赖于 hms 的顺序,您可以使用 1、2 或 3 个值。类似于:

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;
}

如果您想使用原始减速器(来自引用的答案),这可能是一个想法:

const toMS = ts => {
    let raw = ts.split(` `);
    const hms = `0h 0m 0s`.split(` `)
      .map(v => raw.find(t => t.slice(-1) === v.slice(-1)) || v);

    return hms.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`,
  `30m 1s = ${toMS(`30m 1s`)}ms`,
  `15s = ${toMS(`15s`)}ms`,
  `1h = ${toMS(`1h`)}ms`,
  `1m = ${toMS(`1m`)}ms`,
  `1s = ${toMS(`1s`)}ms`,
  `1h 2s = ${toMS(`1h 2s`)}ms`,
  `2h 1s = ${toMS(`2h 1s`)}ms`,
  `1s 6h 2m = ${toMS(`1s 6h 2m`)}ms` ].join(`\n`));
.as-console-wrapper {
  max-height: 100% !important;
}

See Stackblitz snippet 两种解决方案。

如果你想要更强大的东西,试试这个:

const timeString = '1h 30m 1s';
const milliseconds = timeString.match(/\d+\s?\w/g)
    .reduce((acc, cur, i) => {
        var multiplier = 1000;
         switch (cur.slice(-1)) {
            case 'h':
                multiplier *= 60;
            case 'm':
                multiplier *= 60;
            case 's':
                return ((parseInt(cur)?parseInt(cur):0) * multiplier) + acc;
        }
        return acc;
    }, 0);
console.log(milliseconds);

这可以处理任何顺序的时间字符串,例如“12s 5m 1h”,并且会忽略无关元素,甚至可以处理 'in 1 hour 24 minutes and 3 seconds'.

这样的字符串