Duration Parser For Human Time Strings
Parse compact durations such as 1h30m, 500ms or 2.5s into milliseconds with unit validation and clear syntax errors.
Code
const UNITS: Readonly<Record<string, number>> = {
ms: 1,
s: 1_000,
m: 60_000,
h: 3_600_000,
d: 86_400_000,
w: 604_800_000,
};
export function parseDuration(input: string): number {
if (typeof input !== "string") throw new TypeError("input must be a string");
const text = input.trim().toLowerCase();
if (text === "") throw new SyntaxError("duration must not be empty");
if (text.startsWith("-") || text.startsWith("+")) {
throw new RangeError("signed durations are not supported");
}
const pattern = /(\d+(?:\.\d+)?)\s*(ms|s|m|h|d|w)/g;
let total = 0;
let lastIndex = 0;
let matched = false;
let match: RegExpExecArray | null;
while ((match = pattern.exec(text)) !== null) {
const gap = text.slice(lastIndex, match.index);
if (gap.trim() !== "") throw new SyntaxError("invalid duration: " + input);
const amount = Number(match[1]);
const unit = match[2];
total += amount * (UNITS[unit] ?? 0);
lastIndex = pattern.lastIndex;
matched = true;
}
if (!matched || text.slice(lastIndex).trim() !== "") {
throw new SyntaxError("invalid duration: " + input);
}
if (!Number.isFinite(total)) throw new RangeError("duration is too large");
return Math.round(total);
}Report a problem with this exampleOpens a pre-filled issue on GitHub.