Skip to content

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): number

Parameters ​

NameDescription
inputThe 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'); // -30000

Tests ​

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

Generated from the JSDoc of the sources.