Openstatus
www.openstatus.dev
1import type { Incident } from "@openstatus/db/src/schema";
2import { formatDuration } from "./duration";
3
4/**
5 * Get formatted incident duration
6 *
7 * Returns duration string only if incident is resolved (has resolvedAt timestamp).
8 * Returns null for ongoing incidents or if startedAt is missing.
9 *
10 * @example
11 * // Resolved incident
12 * getIncidentDuration({
13 * startedAt: new Date('2026-01-22T10:00:00Z'),
14 * resolvedAt: new Date('2026-01-22T12:15:30Z')
15 * }) // "2h 15m 30s"
16 *
17 * // Ongoing incident
18 * getIncidentDuration({
19 * startedAt: new Date('2026-01-22T10:00:00Z'),
20 * resolvedAt: null
21 * }) // null
22 *
23 * @param incident - The incident object
24 * @returns Formatted duration string or null if incident is not resolved
25 */
26export function getIncidentDuration(incident: Incident): string | null {
27 if (!incident.startedAt) {
28 return null;
29 }
30
31 // Only calculate duration for resolved incidents
32 if (!incident.resolvedAt) {
33 return null;
34 }
35
36 const startTime =
37 incident.startedAt instanceof Date
38 ? incident.startedAt.getTime()
39 : incident.startedAt;
40
41 const endTime =
42 incident.resolvedAt instanceof Date
43 ? incident.resolvedAt.getTime()
44 : incident.resolvedAt;
45
46 const durationMs = endTime - startTime;
47
48 if (durationMs < 0) {
49 return null;
50 }
51
52 return formatDuration(durationMs);
53}