Esto es lo que probé de la respuesta aceptada de esta pregunta
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 Pero, aquí está el problema, si solo pongo 1m por ejemplo, la salida esperada debería ser 60000 milisegundos
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: 60000Piensa que el primer argumento es una hora, luego un minuto seguido de un segundo. No importa lo que ingrese. Así que cuando pongo 1m, piensa que es una hora. Es un formato h, m & s fijo y no puedo intercambiarlos.
La solución que quiero es que debería poder intercambiarlos como horas, m por minutos y s por segundos sin importar el orden y poder elegir solo h, m o s como
Si solo emito 1 m, debería generar solo 1 minuto y así sucesivamente
const timeString = '1m` // should output 60000 const timeString = '2h 1s` // should output 7201000Si los intercambio, aún debería generar el mismo resultado ya que s es un segundo y h es una hora
const timeString = '1s 2h` // should output 7201000 const timeString = '1s` // should output 1000o intercambiarlos como quiera, sin importar el formato que use, y aún debería generar el resultado deseado en milisegundos
const timeString = '1s 6h 2m` // should output 21721000Si quieres algo más robusto, prueba esto:
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);Esto puede manejar cadenas de tiempo en cualquier orden como '12s 5m 1h' e ignorará elementos extraños e incluso manejará cadenas como 'en 1 hora 24 minutos y 3 segundos'.
Divida la cadena (en espacios) y dentro del reductor determine qué valor usar, según el valor de la cadena (la parte 'hms'). En ese caso, no depende del orden de hms y puede usar 1, 2 o 3 valores. Algo como:
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; }Si desea utilizar el reductor original (de la respuesta citada), esta puede ser una idea para eso:
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; }Consulte el fragmento de código de Stackblitz para ambas soluciones.