Tiny, typed number formatting for JavaScript — a modern alternative to Numeral.js.
Numeral.js has 2M+ weekly downloads but hasn't shipped a release since 2017, with 300+ open issues. numly covers the formatting patterns people actually use, in a fresh, tested, typed implementation:
- 🎯 Familiar patterns —
"0,0.00","0.0a","$0,0","0%","0b","0o","00:00:00" - 🪶 ~3 KB gzipped, zero dependencies, tree-shakeable functional API
- 🦺 TypeScript-first — types shipped, no
@types/*needed - 📦 Dual ESM + CJS
- ⚡ ~2× faster than Numeral.js (see benchmark)
- 🌍 Locales —
enandkobuilt in, register your own in 6 lines - 🧮 Float-safe arithmetic —
numly(0.1).add(0.2).value() === 0.3
npm install numlyimport numly from "numly";
numly(1234567).format("0,0"); // "1,234,567"
numly(1234.567).format("0,0.00"); // "1,234.57"
numly(1234567).format("0.0a"); // "1.2m"
numly(0.976).format("0.0%"); // "97.6%"
numly(1000).format("$0,0.00"); // "$1,000.00"
numly(1024).format("0b"); // "1KB"
numly(1024).format("0 ib"); // "1 KiB"
numly(3).format("0o"); // "3rd"
numly(63846).format("00:00:00"); // "17:44:06"
numly(-1000).format("(0,0)"); // "(1,000)"
numly(1234).format("0.0e+0"); // "1.2e+3"Parsing works in reverse — pass a string:
numly("1,000.50").value(); // 1000.5
numly("1.2m").value(); // 1200000
numly("($1.23)").value(); // -1.23
numly("97.6%").value(); // 0.976
numly("2 KiB").value(); // 2048
numly("17:44:06").value(); // 63846Chainable, float-safe arithmetic:
numly(0.1).add(0.2).value(); // 0.3 (not 0.30000000000000004)
numly(1000).add("1,500").format(); // "2,500"
numly(100).clone().multiply(1.1); // originals are never mutated by clone()
numly(5).difference(8); // 3| Pattern | Input | Output |
|---|---|---|
0,0 |
1234567 |
1,234,567 |
0,0.00 |
1234.567 |
1,234.57 |
0.0[00] |
2.5 |
2.5 (optional decimals trimmed) |
0,0[.]00 |
1000 |
1,000 (decimal part optional) |
000 |
5 |
005 |
+0 |
5 |
+5 |
(0,0) |
-1000 |
(1,000) |
0.0a |
1234567 |
1.2m |
0.0 a |
1234567 |
1.2 m |
$0,0.00 |
1000 |
$1,000.00 |
0,0 $ |
1000 |
1,000 $ |
0% |
1 |
100% |
0b / 0.0b |
2000000 |
2MB (decimal, base 1000) |
0ib / 0 ib |
1048576 |
1MiB (binary, base 1024) |
0o |
22 |
22nd |
00:00:00 |
63846 |
17:44:06 |
0.0e+0 |
1234 |
1.2e+3 |
Custom rounding: numly(1.7).format("0", Math.floor) → "1".
numly.locale("ko");
numly(1000).format("$0,0"); // "₩1,000"
numly(1500).format("0.0a"); // "1.5천"
numly(3).format("0o"); // "3번째"
numly.register("de", {
delimiters: { thousands: ".", decimal: "," },
abbreviations: { thousand: "k", million: "M", billion: "Mrd", trillion: "B" },
ordinal: () => ".",
currency: { symbol: "€" },
});
numly.locale("de");
numly(1234.5).format("0,0.00"); // "1.234,50"Tree-shakeable named exports, no instance needed:
import { format, unformat } from "numly";
format(1234.5, "0,0.00"); // "1,234.50"
unformat("1,234.50"); // 1234.5npm run bench — Node.js v20, tinybench, 1,000 mixed values per iteration.
| Scenario | Numeral.js | numly | Speedup |
|---|---|---|---|
format("0,0.00") |
313 ops/s | 556 ops/s | 1.8× |
format("0.0a") |
307 ops/s | 730 ops/s | 2.4× |
unformat |
246k ops/s | 443k ops/s | 1.8× |
The core API is the same shape — for most codebases it's an import swap:
- import numeral from "numeral";
+ import numly from "numly";
- numeral(1000).format("0,0");
+ numly(1000).format("0,0");Covered: format, value, set, add, subtract, multiply, divide, difference, clone, string parsing, custom rounding functions, locale registration. Not covered (rarely used): custom format plugins, numeral.validate, per-locale currency position overrides — open an issue if you need one.
MIT © creepem
2017년 이후 배포가 멈춘 Numeral.js의 현대적 대체재입니다. 동일한 포맷 패턴, TypeScript 타입 내장, ESM/CJS 듀얼 지원, 약 3KB. ko 로케일이 기본 내장되어 ₩, 천/백만, 번째 포맷을 바로 쓸 수 있습니다.