Karty
Karty

Reputation: 1399

Calculate minutes from string of minutes and hours or days and hours

I have a function which takes a string of hours and minutes or days and hours and convert it to minutes.

calculate(s) {
    const matches = /(?:(\d+) hours?)? ?(?:(\d+) mins?)?/.exec(s);
    return Number(matches[1] || 0) * 60 + Number(matches[2] || 0);
};

I could somehow manage to find minutes if the inputs were:

console.log(calculate('1 hour 5 mins')); // 65
console.log(calculate('2 hours 1 min')); // 121
console.log(calculate('3 hours')); // 180
console.log(calculate('10 mins')); // 10

But how do I find the minutes if the inputs were:

console.log(calculate('1 day 5 hours'));
console.log(calculate('2 days 15 hours'));
console.log(calculate('3 days 16 hours 32 mins'));

Upvotes: 2

Views: 178

Answers (2)

pretzelhammer
pretzelhammer

Reputation: 15115

Below solution works for all of your examples. Also would work if you skipped certain units, e.g. 1 day 3 mins (no hours), or put the units out of order, e.g. 5 mins 10 hours.

function calculate(time) {
  // split string into words
  let times = time.split(/\s+/);
  
  let totalMinutes = 0;
  while (times.length > 0) {
    // get quantity from number in pair
    let quantity = Number(times.shift());
    // get unit of measurement from pair
    let unit = times.shift();
    let multipler;
    if (/day/.test(unit)) {
      // there are 60 * 24 minutes in a day
      multipler = 60 * 24;
    } else if (/hour/.test(unit)) {
      // there are 60 minutes in an hour
      multipler = 60;
    } else { // assuming minute
      // there's 1 minute in a minute
      multipler = 1;
    }
    // add to the total amount of minutes
    totalMinutes += quantity * multipler;
  }

  return totalMinutes;
}

console.log(calculate('1 hour 5 mins')); // 65
console.log(calculate('2 hours 1 min')); // 121
console.log(calculate('3 hours')); // 180
console.log(calculate('10 mins')); // 10
console.log(calculate('1 day 5 hours')); // 1740
console.log(calculate('2 days 15 hours')); // 3780
console.log(calculate('3 days 16 hours 32 mins')); // 5312
console.log(calculate('2 hours')); // 120
console.log(calculate('1 day')); // 1440

Upvotes: 1

Corion
Corion

Reputation: 3925

Just add the days part in front of the hours part, using the same logic:

(?:(\d+) days? ?)?(?:(\d+) hours? ?)?(?:(\d+) mins?)?

In code, this would be:

    function calculateMinutes(s) {
        const matches = /(?:(\d+) days? ?)?(?:(\d+) hours? ?)?(?:(\d+) mins?)?/.exec(s);
        return   Number(matches[1] || 0) * 24*60
               + Number(matches[2] || 0) * 60
               + Number(matches[3] || 0);
    };
    console.log(calculateMinutes('1 hour 5 mins')); // 65
    console.log(calculateMinutes('2 hours 1 min')); // 121
    console.log(calculateMinutes('3 hours')); // 180
    console.log(calculateMinutes('10 mins')); // 10
    console.log(calculateMinutes('1 day 5 hours')); // 1740
    console.log(calculateMinutes('2 days 15 hours')); // 3780
    console.log(calculateMinutes('3 days 16 hours 32 mins')); // 5312
    console.log(calculateMinutes('2 hours')); // 120
    console.log(calculateMinutes('1 day')); // 1440
    console.log(calculateMinutes('1 day 16 hours')); 

Regex fiddle

Upvotes: 2

Related Questions