I have a strange format case with date-fns and formatting duration. If somebody have an idea what I'm doing wrong:
function formatDuration(duration) {
return duration >= 60000 * 60
? format(new Date(duration), "hh 'h', mm 'min', ss 'sec'")
: duration >= 60000
? format(new Date(duration), "mm 'min', ss 'sec'")
: format(new Date(duration), "ss 'sec'");
}
What I expect:
formatDuration((59 * 60 + 59) * 1000); // '59 min, 59 sec'
formatDuration((60 * 60) * 1000); // '01 h 00 min, 00 sec'
What I get:
formatDuration((59 * 60 + 59) * 1000); // '59 min, 59 sec'
formatDuration((60 * 60) * 1000); // '02 h 00 min, 00 sec'
In the second case, there is an extra hour appearing from nowhere. I don't understand where the problem is. Any idea? Thanks!
Some of you were true that using Date was not a good idea. Manipulating number was more successfull. Here is my solution to my problem:
function formatDuration(duration) {
if (!duration) {
return '';
}
const durationSeconds = duration / 1000;
const hours = Math.floor(durationSeconds / 3600);
const restHours = durationSeconds % 3600;
const minutes = Math.floor(restHours / 60);
const seconds = restHours % 60;
const hoursPart = hours > 0 ? `${hours} h, ` : '';
let minutesPart;
if (hours > 0) {
if (minutes > 0) {
minutesPart = `${minutes.toString().padStart(2, '0')} min, `;
} else {
minutesPart = '00 min, ';
}
} else {
if (minutes > 0) {
minutesPart = `${minutes} min, `;
} else {
minutesPart = '';
}
}
let secondsPart;
if (hours > 0 || minutes > 0) {
if (seconds > 0) {
secondsPart = `${seconds.toString().padStart(2, '0')} sec`;
} else {
secondsPart = '00 sec';
}
} else {
if (seconds > 0) {
secondsPart = `${seconds} sec`;
} else {
secondsPart = '';
}
}
return `${hoursPart}${minutesPart}${secondsPart}`;
}
Maybe there is a more simple solution than this one but its working well and it's ok for all my cases.
Tested with this, all green:
describe('duration_format', () => {
const cases = [
[2, '2 sec'],
[9, '9 sec'],
[14, '14 sec'],
[23, '23 sec'],
[36, '36 sec'],
[47, '47 sec'],
[51, '51 sec'],
[59, '59 sec'],
[60, '1 min, 00 sec'],
[61, '1 min, 01 sec'],
[82, '1 min, 22 sec'],
[154, '2 min, 34 sec'],
[887, '14 min, 47 sec'],
[30 * 60 + 22, '30 min, 22 sec'],
[59 * 60 + 22, '59 min, 22 sec'],
[59 * 60 + 59, '59 min, 59 sec'],
[60 * 60, '1 h, 00 min, 00 sec'],
[12 * 60 * 60 + 45 * 60 + 22, '12 h, 45 min, 22 sec'],
];
test.each(cases)('%s to %s', (duration, humanReadable) => {
expect(formatDuration(duration * 1000)).toBe(humanReadable);
});
});