Deno v2.5.3
deno run https://gist.github.com/jihchi/2d993c308031cf848c404acd06bf0f8a/raw/solve.tsDeno v2.5.3
deno run https://gist.github.com/jihchi/2d993c308031cf848c404acd06bf0f8a/raw/solve.ts| const MIN = 60 * 1000; | |
| const groupChangelogEdits = ( | |
| edits: { timestamp: string; component: string }[], | |
| ) => { | |
| const map = edits.reduce<Map<string, Date[]>>( | |
| (acc, { component, timestamp }) => { | |
| if (!acc.has(component)) { | |
| acc.set(component, []); | |
| } | |
| acc.get(component)?.push(new Date(timestamp)); | |
| return acc; | |
| }, | |
| new Map(), | |
| ); | |
| for (const [_component, dates] of map) { | |
| dates.sort(); | |
| } | |
| return Array.from(map.keys()) | |
| .flatMap((component) => { | |
| const [firstDate, ...dates] = map.get(component) ?? []; | |
| const grouped = [ | |
| { | |
| component, | |
| start: firstDate, | |
| end: firstDate, | |
| }, | |
| ]; | |
| let windowEnd = new Date(firstDate.getTime() + 10 * MIN); | |
| for (const date of dates) { | |
| if (date > windowEnd) { | |
| windowEnd = new Date(date.getTime() + 10 * MIN); | |
| grouped.push({ | |
| component, | |
| start: date, | |
| end: date, | |
| }); | |
| } else { | |
| const prev = grouped[grouped.length - 1]; | |
| prev.end = new Date(Math.max(prev.end.getTime(), date.getTime())); | |
| } | |
| } | |
| return grouped; | |
| }) | |
| .map(({ component, start, end }) => ({ | |
| component, | |
| start: start.toISOString().split(".")[0] + "Z", | |
| end: end.toISOString().split(".")[0] + "Z", | |
| })); | |
| }; | |
| console.log( | |
| groupChangelogEdits([ | |
| { timestamp: "2025-10-06T08:20:00Z", component: "Header" }, | |
| { timestamp: "2025-10-06T08:05:00Z", component: "Header" }, | |
| { timestamp: "2025-10-06T08:00:00Z", component: "Header" }, | |
| { timestamp: "2025-10-06T08:15:00Z", component: "Footer" }, | |
| { timestamp: "2025-10-06T08:07:00Z", component: "Footer" }, | |
| ]), | |
| ); |