Add computeTransferMinutes and formatMinutesAsDuration helpers

This commit is contained in:
2026-04-17 02:26:33 +03:00
parent 6854d93344
commit 81d04bdc49
2 changed files with 76 additions and 0 deletions
@@ -0,0 +1,47 @@
import { describe, it, expect } from "vitest";
import { computeTransferMinutes, formatMinutesAsDuration } from "./computeTransferTime.js";
describe("computeTransferMinutes", () => {
it("returns positive diff in minutes", () => {
expect(computeTransferMinutes("2026-04-17T10:00:00Z", "2026-04-17T11:30:00Z")).toBe(90);
});
it("returns 0 when times are identical", () => {
const t = "2026-04-17T10:00:00Z";
expect(computeTransferMinutes(t, t)).toBe(0);
});
it("returns null when departure is before arrival (negative)", () => {
expect(computeTransferMinutes("2026-04-17T11:00:00Z", "2026-04-17T10:00:00Z")).toBeNull();
});
it("returns null when arrival is undefined", () => {
expect(computeTransferMinutes(undefined, "2026-04-17T10:00:00Z")).toBeNull();
});
it("returns null when departure is undefined", () => {
expect(computeTransferMinutes("2026-04-17T10:00:00Z", undefined)).toBeNull();
});
it("returns null for invalid ISO strings", () => {
expect(computeTransferMinutes("not-a-date", "2026-04-17T10:00:00Z")).toBeNull();
});
});
describe("formatMinutesAsDuration", () => {
it("formats 90 minutes as '1h 30m'", () => {
expect(formatMinutesAsDuration(90)).toBe("1h 30m");
});
it("formats 45 minutes as '45m'", () => {
expect(formatMinutesAsDuration(45)).toBe("45m");
});
it("formats 60 minutes as '1h'", () => {
expect(formatMinutesAsDuration(60)).toBe("1h");
});
it("formats 0 as '0m'", () => {
expect(formatMinutesAsDuration(0)).toBe("0m");
});
});
@@ -0,0 +1,29 @@
import { parseISO, differenceInMinutes, isValid } from "date-fns";
/**
* Diff (in minutes) between departure and arrival ISO UTC strings.
* Returns null when either input is missing/invalid, or when result is negative.
*/
export function computeTransferMinutes(
arrivalUtc: string | undefined,
departureUtc: string | undefined,
): number | null {
if (!arrivalUtc || !departureUtc) return null;
const arr = parseISO(arrivalUtc);
const dep = parseISO(departureUtc);
if (!isValid(arr) || !isValid(dep)) return null;
const diff = differenceInMinutes(dep, arr);
if (diff < 0) return null;
return diff;
}
/**
* Format a minute count as "Nh Mm" (or "Mm" when <1 hour, or "Nh" when no remainder).
*/
export function formatMinutesAsDuration(minutes: number): string {
if (minutes < 60) return `${minutes}m`;
const h = Math.floor(minutes / 60);
const m = minutes % 60;
if (m === 0) return `${h}h`;
return `${h}h ${m}m`;
}