api: carry rounded minutes into the hour in formatHours
formatHours rounded the leftover minutes but never carried them, so a value like 7.999 rendered as "7h 60min" instead of "8h". The remainder is now carried into the hour before the string is built, and a test pins it
Pedro Lucas Porcellis porcellis@eletrotupi.com · 10 days ago
5dc751d753dcbc4f8d8a9f461b79992e8ba1c9ac Browse filesParents
b444500Changed files
2
Additions
+12
Deletions
-2
api/src/utils/calc.ts
1 1
// TODO: Move other calculations here
2 2
export const avg = (values: number[]) =>
3 3
values.reduce((a, b) => a + b, 0) / values.length;
4 4
5 5
export const formatHours = (hours: number): string => {
6 -
const h = Math.floor(hours);
7 -
const m = Math.round((hours - h) * 60);
6 +
let h = Math.floor(hours);
7 +
let m = Math.round((hours - h) * 60);
8 +
9 +
// Rounding to the nearest minute can land on 60; carry it into the hour
10 +
if (m === 60) {
11 +
h += 1;
12 +
m = 0;
13 +
}
8 14
9 15
if (m === 0) return `${h}h`;
10 16
11 17
return `${h}h ${m}min`;
12 18
}
20 26
if (h === 0) return `${sign}${m}min`;
21 27
if (m === 0) return `${sign}${h}h`;
22 28
23 29
return `${sign}${h}h ${m}min`;
24 30
}
api/tests/utils/calc.unit.test.ts
1 1
import { describe, it, expect } from 'vitest'
2 2
import { avg, formatHours, formatDiff } from '@app/utils/calc'
3 3
4 4
describe('avg', () => {
5 5
it('averages a list of numbers', () => {
17 17
})
18 18
19 19
it('renders the remaining minutes', () => {
20 20
expect(formatHours(7.5)).toBe('7h 30min')
21 21
})
22 +
23 +
it('carries a rounding of sixty minutes into the next hour', () => {
24 +
expect(formatHours(7.999)).toBe('8h')
25 +
})
22 26
})
23 27
24 28
describe('formatDiff', () => {
25 29
it('signs a positive whole-hour difference', () => {
26 30
expect(formatDiff(120)).toBe('+2h')
44 48
45 49
it('renders a negative sub-hour difference in minutes only', () => {
46 50
expect(formatDiff(-30)).toBe('-30min')
47 51
})
48 52
})