-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsolution.ts
More file actions
56 lines (44 loc) · 1.61 KB
/
solution.ts
File metadata and controls
56 lines (44 loc) · 1.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* Convert a non-negative millisecond duration into a compact human-friendly string
* using units d, h, m, s.
* Rules applied:
* - Use floor division
* - Omit zero-valued units
* - Show at most two largest non-zero units (e.g. "2d 3h", "1h 2m", "45s")
* - For ms <= 0 or invalid input return '0s'
*/
export function formatTimeRemaining(ms: number): string {
// Validate input: must be a finite number greater than 0
if (typeof ms !== 'number' || !Number.isFinite(ms) || ms <= 0) return '0s';
// Convert to whole seconds using floor division
const totalSeconds = Math.floor(ms / 1000);
if (totalSeconds <= 0) return '0s';
// Seconds per unit
const SECONDS_PER_DAY = 86400; // 24 * 3600
const SECONDS_PER_HOUR = 3600;
const SECONDS_PER_MINUTE = 60;
let remaining = totalSeconds;
const days = Math.floor(remaining / SECONDS_PER_DAY);
remaining -= days * SECONDS_PER_DAY;
const hours = Math.floor(remaining / SECONDS_PER_HOUR);
remaining -= hours * SECONDS_PER_HOUR;
const minutes = Math.floor(remaining / SECONDS_PER_MINUTE);
remaining -= minutes * SECONDS_PER_MINUTE;
const seconds = remaining;
// Ordered from largest to smallest
const units: Array<[number, string]> = [
[days, 'd'],
[hours, 'h'],
[minutes, 'm'],
[seconds, 's'],
];
// Keep only non-zero units
const nonZero = units.filter(([value]) => value > 0);
if (nonZero.length === 0) {
// No non-zero unit (e.g., ms < 1000 but > 0)
return '0s';
}
// Show at most two largest non-zero units
const shown = nonZero.slice(0, 2);
return shown.map(([value, label]) => `${value}${label}`).join(' ');
}