Store money as an integer amount in the currency's smallest unit, together with its currency code. Format it with Intl.NumberFormat only when you display it.
Storing:
- Save
{ amount: 1999, currency: "EUR" }for €19.99. Integers avoid floating-point errors, because0.1 + 0.2is0.30000000000000004in JavaScript. - Always store the currency code (ISO 4217, like
USD,EGP,JPY). A number alone means nothing. - Remember that the smallest unit differs: cents for USD, but JPY has no minor unit, and KWD has 3 decimals.
Calculating:
- Do the math on the server, in integers. Decide the rounding rule for tax and discounts.
- Never add amounts in different currencies. Convert with a known rate first.
Displaying:
new Intl.NumberFormat(locale, { style: "currency", currency }).format(amount / 100)for a 2-decimal currency.- The locale decides how it looks:
de-DEshows "19,99 €",en-USshows "€19.99". - The currency decides what it is. Don't guess the currency from the locale. A German speaker in Switzerland may pay in CHF, and an English page may show prices in EGP.
- Use
currencyDisplay: "code"("USD 5.00") when "$" could mean US, Canadian or Australian dollars.
- Store prices as integers in the smallest unit, with the currency code.
- Integers avoid floating-point rounding errors.
- Each currency has its own number of decimals, like 0 for JPY.
- The locale decides the format, and the currency is a separate setting you must not guess.
- Format with
Intl.NumberFormatandstyle: "currency"only at display time.