Shyamal Parikh
Shyamal Parikh

Reputation: 3068

Javascript: Parse string to duration

How to parse strings like 1h 20m, 30m, 1 h, 1 h 30m, 2:45 to timespan. While rejecting 34r 45g, 10:75 etc.

Tried with the following code:

function parse(str){
  var result = 0
  // ignore commas
  str = str.replace(/(\d),(\d)/g, '$1$2')
  str.replace(duration, function(_, n, units){
    units = getUnits(units)
      || getUnits[units.toLowerCase().replace(/s$/, '')]
      || 1
    result += parseFloat(n, 10) * units;
  })
  return result;
}

function getUnits(unit){
  var to_ret;
  switch(unit){
    case "seconds":
    case "second":
    case "secs":
    case "sec":
    case "s": to_ret = 0; break;

    case "minutes":
    case "minute":
    case "mins":
    case "min":
    case "m": to_ret = 1; break;

    case "hours":
    case "hour": 
    case "hr":
    case "hrs":
    case "h": to_ret =  60; break;

    case "days":
    case "day":
    case "d": to_ret = 24 * 60; break;

    case "weeks":
    case "week":
    case "w": to_ret = 7 * 24 * 60; break;

    default: to_ret = undefined;
  }

  return to_ret;
}

Plunker for above code: https://plnkr.co/edit/7V0Lgj?p=preview

However, the above isn't good enough to recognize what 2:45 means while doesn't give error with 34r,45g, 10:75.

Now, I could add more conditions however, would like to know if any simple solution to the above issue is available

Upvotes: 1

Views: 467

Answers (1)

Michał Sałaciński
Michał Sałaciński

Reputation: 2266

Format H:M is kind of different, so I wouldn't try to solve it with 1 regex/1 loop. Also, why settle with multiplier *1 when letters can't be parsed to hours/minutes etc? So, with some error handling, this should be ok: plnkr

function parse(str){
  var result = 0
  var error = null;
  // ignore commas
  str = str.replace(/(\d),(\d)/g, '$1$2')
  if (str.indexOf(':')>=0) {
    var arr = str.split(':')
    if (arr.length != 2) error = true;
    else result = parseInt(arr[0])*60+ parseInt(arr[1])

  }
  else str.replace(duration, function(_, n, units){
    units = getUnits(units)
      || getUnits[units.toLowerCase().replace(/s$/, '')]
      || undefined;
    if (typeof units === 'undefined') error = true;
    else result += parseFloat(n, 10) * units;

  })
  return error?null:result;
}

Upvotes: 1

Related Questions