parseTimeSpan function
Parses a .NET TimeSpan into milliseconds: the constant format c (1.02:03:04.5670000, the JSON one) or the general formats g / G (1:02:03:04.567). The 100 ns ticks become decimals of milliseconds.
ts
import { parseTimeSpan } from 'utils';Signature
ts
export function parseTimeSpan(input: string): numberParameters
| Name | Description |
|---|---|
input | The TimeSpan text; surrounding spaces are ignored. |
Returns
The duration in milliseconds, negative for a negative TimeSpan.
Errors
- Throws TypeError: When the text is not a
TimeSpan.
Example
ts
parseTimeSpan('1.02:03:04.5670000'); // 93784567
parseTimeSpan('-00:00:30'); // -30000Tests
Line coverage: 100 %.
- ✅ parses "1.02:03:04.5670000" as 93784567 ms
- ✅ parses "00:00:30" as 30000 ms
- ✅ parses "-00:00:30" as -30000 ms
- ✅ parses "1:02:03:04.567" as 93784567 ms
- ✅ parses " 12:00:00 " as 43200000 ms
- ✅ parses "00:00:00.0000001" as 0.0001 ms
- ✅ parses "00:00:00.5" as 500 ms
- ✅ parses "00:00:00,25" as 250 ms
- ✅ parses "10675199.02:48:05.4775807" as 922337203685477.6 ms
- ✅ throws a TypeError for ""
- ✅ throws a TypeError for "30"
- ✅ throws a TypeError for "1:2:3"
- ✅ throws a TypeError for "00:00:00.12345678"
- ✅ throws a TypeError for "a.00:00:00"
- ✅ throws a TypeError for "1.2.00:00:00"
Source
src/duration/parse-time-span.ts (on GitHub)
Source code
ts
const MS_PER_SECOND = 1000;
const MS_PER_MINUTE = 60_000;
const MS_PER_HOUR = 3_600_000;
const MS_PER_DAY = 86_400_000;
const TICKS_PER_MS = 10_000;
const TICK_DIGITS = 7;
const TIME_SPAN_PATTERN =
/^(?<sign>-)?(?:(?<days>\d+)[.:])?(?<hours>\d{1,2}):(?<minutes>\d{2}):(?<seconds>\d{2})(?:[,.](?<fraction>\d{1,7}))?$/v;
/**
* Parses a .NET `TimeSpan` into milliseconds: the constant format `c` (`1.02:03:04.5670000`, the JSON one)
* or the general formats `g` / `G` (`1:02:03:04.567`). The 100 ns ticks become decimals of milliseconds.
*
* @param input - The `TimeSpan` text; surrounding spaces are ignored.
* @returns The duration in milliseconds, negative for a negative `TimeSpan`.
* @throws {TypeError} When the text is not a `TimeSpan`.
* @example
* parseTimeSpan('1.02:03:04.5670000'); // 93784567
* parseTimeSpan('-00:00:30'); // -30000
*/
export function parseTimeSpan(input: string): number {
const groups = TIME_SPAN_PATTERN.exec(input.trim())?.groups;
if (!groups) {
throw new TypeError(`Invalid TimeSpan: '${input}'`);
}
const ticks = Number((groups['fraction'] ?? '').padEnd(TICK_DIGITS, '0'));
const milliseconds =
Number(groups['days'] ?? 0) * MS_PER_DAY +
Number(groups['hours']) * MS_PER_HOUR +
Number(groups['minutes']) * MS_PER_MINUTE +
Number(groups['seconds']) * MS_PER_SECOND +
ticks / TICKS_PER_MS;
return groups['sign'] === undefined ? milliseconds : -milliseconds;
}Test file
ts
import { parseTimeSpan } from './parse-time-span';
describe(parseTimeSpan, () => {
it.for([
['1.02:03:04.5670000', 93_784_567],
['00:00:30', 30_000],
['-00:00:30', -30_000],
['1:02:03:04.567', 93_784_567],
[' 12:00:00 ', 43_200_000],
['00:00:00.0000001', 0.0001],
['00:00:00.5', 500],
['00:00:00,25', 250],
['10675199.02:48:05.4775807', 922_337_203_685_477.6],
] as const)('parses %j as %s ms', ([input, expected]) => {
expect(parseTimeSpan(input)).toBeCloseTo(expected, 4);
});
it.for(['', '30', '1:2:3', '00:00:00.12345678', 'a.00:00:00', '1.2.00:00:00'])(
'throws a TypeError for %j',
(input) => {
expect(() => parseTimeSpan(input)).toThrow(TypeError);
},
);
});Keywords: parse, time, span, durations, function