locutus
Version:
Locutus other languages' standard libraries to JavaScript for fun and educational purposes
59 lines (58 loc) • 2.01 kB
JavaScript
const DURATION_UNIT_TO_MS = {
ns: 1e-6,
us: 1e-3,
'\u00b5s': 1e-3,
ms: 1,
s: 1_000,
m: 60_000,
h: 3_600_000,
};
const DURATION_PART_REGEX = /^(\d+(?:\.\d+)?|\.\d+)(ns|us|\u00b5s|ms|s|m|h)/;
export function ParseDuration(s) {
// discuss at: https://locutus.io/golang/time/ParseDuration
// parity verified: Go 1.23
// original by: Kevin van Zonneveld (https://kvz.io)
// note 1: Parses Go duration strings and returns milliseconds.
// note 2: Supports ns, us/µs, ms, s, m, h units and chained segments.
// example 1: ParseDuration('300ms')
// returns 1: 300
// example 2: ParseDuration('1h2m3.5s')
// returns 2: 3723500
// example 3: ParseDuration('-1.5h')
// returns 3: -5400000
// example 4: ParseDuration('2h45m')
// returns 4: 9900000
const raw = String(s).trim();
if (raw === '') {
throw new TypeError('ParseDuration(): invalid duration');
}
let sign = 1;
let rest = raw;
if (rest.startsWith('+') || rest.startsWith('-')) {
sign = rest[0] === '-' ? -1 : 1;
rest = rest.slice(1);
}
if (rest === '0') {
return 0;
}
let totalMs = 0;
while (rest.length > 0) {
const match = DURATION_PART_REGEX.exec(rest);
if (!match) {
throw new TypeError('ParseDuration(): invalid duration');
}
const valueLiteral = match[1];
const unit = match[2];
if (!valueLiteral || !unit) {
throw new TypeError('ParseDuration(): invalid duration');
}
const value = Number.parseFloat(valueLiteral);
const multiplier = DURATION_UNIT_TO_MS[unit];
if (!Number.isFinite(value) || multiplier === undefined) {
throw new TypeError('ParseDuration(): invalid duration');
}
totalMs += value * multiplier;
rest = rest.slice(match[0].length);
}
return sign * totalMs;
}