/
convert-many.ts
74 lines (61 loc) · 1.89 KB
/
convert-many.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { BestKind } from '../conversions/types';
import { BestConversion, Converter } from '../types/converter';
import { convert } from './convert';
import type { BestUnits, Unit } from '../types/units';
const splitExpression = /(-?(?:\d+)?\.?\d+)(\S+)/g;
type ConverterThis = {
_search: RegExpExecArray;
_value: string;
};
function to(this: ConverterThis, unit: Unit | 'best', kind?: BestKind | undefined) {
const isBest = unit === 'best';
let result = 0;
let resolvedUnit: BestUnits;
let isFirstPass = true;
do {
const converted = convert(Number(this._search[1]), this._search[2] as Unit).to(
// biome-ignore lint/style/noNonNullAssertion:
(isBest && !isFirstPass ? resolvedUnit! : unit) as Unit,
) as number | BestConversion<number, BestUnits>;
if (isBest && isFirstPass) {
result += (converted as BestConversion<number, BestUnits>).quantity;
resolvedUnit = (converted as BestConversion<number, BestUnits>).unit;
isFirstPass = false;
} else {
result += converted as number;
}
// biome-ignore lint/style/noNonNullAssertion:
this._search = splitExpression.exec(this._value)!;
} while (this._search);
if (isBest) {
// biome-ignore lint/style/noNonNullAssertion:
return convert(result, resolvedUnit!).to('best', kind);
}
return result;
}
/**
* Convert several values in a string into a single unit.
*
* @example
* ```ts
* convertMany('1d 12h').to('hours') === 36;
* ```
*
* @param value - The string to parse as values
*
* @public
*/
export function convertMany(value: string): Converter<number, Unit> {
splitExpression.lastIndex = 0;
const search = splitExpression.exec(value);
if (!search) {
throw new RangeError(`value did not match expression ${splitExpression.source}`);
}
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return {
to: to.bind({
_search: search,
_value: value,
}),
} as Converter<number, Unit>;
}