numberparrot

Intl.NumberFormat Parse: How to Reverse Intl Number Formatting

Intl.NumberFormat has format, formatToParts and formatRange. There is no parse.

What is missing

example.ts
const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" });
const text = nf.format(-1234.5); // "-1.234,50 €"
nf.parse(text);                  // TypeError: nf.parse is not a function

A parser built on the same data

numberparrot asks Intl.NumberFormat#formatToParts for the decimal, group, minus, percent and exponent symbols and the digits of the numbering system, then parses with them. Whatever Intl writes, numberparrot reads:

example.ts
import { parse, parseCurrency } from "numberparrot";

parse(new Intl.NumberFormat("de-DE").format(1234.5), "de-DE");                       // 1234.5
parse(new Intl.NumberFormat("en-US", { style: "percent" }).format(0.25), "en-US");   // 0.25
parse(new Intl.NumberFormat("sv-SE", { notation: "scientific" }).format(1500), "sv-SE"); // 1500
parse(new Intl.NumberFormat("ar-EG").format(-42.5), "ar-EG");                         // -42.5

const usd = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting" });
parseCurrency(usd.format(-1234.56), "en-US"); // { amount: -1234.56, currency: "USD", ... }

Round trip guarantee

For values printed with enough significant digits (17), parsing gives back exactly the same JavaScript number. The test suite checks this for 17 locales in decimal, scientific, percent, currency and accounting styles:

example.ts
const nf = new Intl.NumberFormat("fr-FR", { maximumSignificantDigits: 17 });
const value = 0.1 + 0.2;
parse(nf.format(value), "fr-FR") === value; // true

Numbering systems and extensions

example.ts
parse(new Intl.NumberFormat("th-TH-u-nu-thai").format(1234.5), "th-TH-u-nu-thai"); // 1234.5
parse(new Intl.NumberFormat("hi-IN-u-nu-deva").format(1234.5), "hi-IN-u-nu-deva"); // 1234.5

Install

Terminal
npm install numberparrot

Zero dependencies, ESM and CommonJS, TypeScript types included. Works in Node.js 18+, Deno, Bun and browsers. Try it in the playground.

More guides