Reputation: 89
I have a field in my table that I would like to sort. That field contains strings from MomentJS duration calculation. For example "20 Minutes", "10 Hours 1 Minute" and so on. If I want to use a sort function I need to format that string back to lowest resolution of time I have which is minutes. Like this: a: "20 Minutes" => 20. b: "10 Hours 1 Minute" => 10*60 + 1 = 601. So when sorting in a descending order b will come before a.
I made this function that does work but it is really hardcoded so I would really like to see other ways to solve it. Thanks!
function getTimeFromDuration(duration) {
const str = duration.split(' ');
const durationArray = ['Minute', 'Minutes', 'Hour', 'Hours', 'Day', 'Days'];
const calcArr = [];
let sum = 0;
for (let i=0; i<str.length; i++) {
const isNum = !isNaN(str[i]);
const isDuration = durationArray.includes(str[i]) > -1;
if (isNum) {
calcArr.push(parseInt(str[i]));
}
else if (isDuration) {
switch(str[i]) {
case 'Minute':
case 'Minutes':
calcArr.push(1);
break;
case 'Hour':
case 'Hours':
calcArr.push(60);
break;
case 'Day':
case 'Days':
calcArr.push(60*24);
break;
}
}
}
for (let j=0; j<calcArr.length; j=j+2) {
sum+= calcArr[j]*calcArr[j+1];
}
return sum;
}
console.log(getTimeFromDuration('1 Day 1 Hour 20 Minutes'));
Upvotes: 0
Views: 107
Reputation: 15130
I am not aware of a parsing function in Moment or elsewhere that will handle these types of strings. If your input strings are consistently formatted and limited to days, hours and minutes, then parsing them should not be all that difficult. Following is an approach along the lines of your original function, just a bit more compact due to some effort put into splitting the string into each duration "chunk" and then normalizing the duration descriptor (lowercase and singular) so you can easily access values from a multiplier object.
That said, if your original data contains the Moment duration object rather than just the string representation, then there are easier ways to do this.
const getMinutes = (s) => {
const multipliers = { day: 1440, hour: 60, minute: 1 };
const durations = s.split(/\s(?=\d)/);
let minutes = 0;
for (const d of durations) {
let [n, interval] = d.split(' ');
n = Number(n);
interval = interval.toLowerCase();
if (interval.endsWith('s')) {
interval = interval.slice(0, -1);
}
minutes += n * multipliers[interval];
}
return minutes;
};
const result = getMinutes('1 Day 1 Hour 20 Minutes');
console.log(result);
// 1520
Upvotes: 1