/
units.ts
110 lines (102 loc) · 2.09 KB
/
units.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { memoizeJ } from "@thi.ng/memoize";
import type { Stringer } from "./api";
type UnitDefs = [number, string, number?][];
export const units: (
exp: UnitDefs,
base: string,
prec?: number
) => Stringer<number> = memoizeJ<
UnitDefs,
string,
number | undefined,
Stringer<number>
>((exp: UnitDefs, base: string, prec: number = 2) => {
const groups = exp
.map(
(x) =>
<[number, number, string]>[
x[0],
x[2] != null ? x[2] : prec,
x[1],
]
)
.sort((a, b) => a[0] - b[0]);
return (x: number) => {
if (x === 0) {
return `0${base}`;
}
const absX = Math.abs(x);
for (let i = groups.length; --i >= 0; ) {
const g = groups[i];
if (absX >= g[0] || i === 0) {
return (x / g[0]).toFixed(g[1]) + g[2];
}
}
return "";
};
});
const KB = 1024;
export const bits = units(
[
[1, " bits", 0],
[KB, " Kb"],
[KB ** 2, " Mb"],
[KB ** 3, " Gb"],
],
" bits",
2
);
export const bytes = units(
[
[1, " bytes", 0],
[KB, " KB"],
[KB ** 2, " MB"],
[KB ** 3, " GB"],
[KB ** 4, " TB"],
[KB ** 5, " PB"],
],
" bytes",
2
);
export const seconds = units(
[
[1e-12, " ps"],
[1e-9, " ns"],
[1e-6, " µs"],
[1e-3, " ms"],
[1, " secs"],
[60, " mins"],
[60 * 60, " hours"],
[24 * 60 * 60, " days"],
],
" secs",
3
);
export const meters = units(
[
[1e-12, " pm"],
[1e-9, " nm"],
[1e-6, " µm"],
[1e-3, " mm"],
[1e-2, " cm"],
[1, " m"],
[1e3, " km"],
],
" m",
2
);
export const grams = units(
[
[1e-12, " pg"],
[1e-9, " ng"],
[1e-6, " µg"],
[1e-3, " mg"],
[1, " g"],
[1e3, " kg"],
[1e6, " t"],
[1e9, " kt"],
[1e12, " Mt"],
],
" g",
2
);