49 lines
1.5 KiB
TypeScript
49 lines
1.5 KiB
TypeScript
export interface SprintLike {
|
|
id: string;
|
|
startDate: string;
|
|
endDate: string;
|
|
status: "planning" | "active" | "completed";
|
|
}
|
|
|
|
function parseSprintStart(value: string): Date {
|
|
const match = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
|
if (match) {
|
|
return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]), 0, 0, 0, 0)
|
|
}
|
|
return new Date(value)
|
|
}
|
|
|
|
function parseSprintEnd(value: string): Date {
|
|
const match = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
|
if (match) {
|
|
return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]), 23, 59, 59, 999)
|
|
}
|
|
const parsed = new Date(value)
|
|
parsed.setHours(23, 59, 59, 999)
|
|
return parsed
|
|
}
|
|
|
|
export function isSprintInProgress(startDate: string, endDate: string, now: Date = new Date()): boolean {
|
|
const sprintStart = parseSprintStart(startDate)
|
|
const sprintEnd = parseSprintEnd(endDate)
|
|
return sprintStart <= now && sprintEnd >= now
|
|
}
|
|
|
|
export function findCurrentSprint<T extends SprintLike>(
|
|
sprints: T[],
|
|
options?: {
|
|
now?: Date
|
|
includeCompletedFallback?: boolean
|
|
}
|
|
): T | null {
|
|
const now = options?.now ?? new Date()
|
|
const includeCompletedFallback = options?.includeCompletedFallback ?? false
|
|
const inProgress = sprints.filter((s) => isSprintInProgress(s.startDate, s.endDate, now))
|
|
|
|
return (
|
|
inProgress.find((s) => s.status === "active") ??
|
|
inProgress.find((s) => s.status !== "completed") ??
|
|
(includeCompletedFallback ? inProgress[0] ?? null : null)
|
|
)
|
|
}
|