const amount = (value, currency = "EUR", long) => {
return (
(Number(value) || 0)
.toFixed(long ? 2 : 0)
.replace(/-/g, "-\u00a0")
.replace(/(\d)(?=(\d{3})+(\.|$))/g, "$1\u00a0")
.replace(".", ",") +
(currency
? "\u00a0" +
({
EUR: "€",
USD: "$",
GBP: "£",
}[currency] || currency)
: "")
);
};
Context
In development we often have to manipulate numbers that need to be represented as amounts to our users. Unfortunately, in javascript there is no native way of doing it.
Well actually there is a native function which as recently been supported in Node 19 thanks to a bump to the latest version of the V8 engine but as we wont be able to use it in production for a while consider this as still relevant :)(Node 19 is a odd numbered release meaning it's not an LTS version, unless it's backported of course).
The amount() function allows us to do it!
Usage
amount(200); // 200 €
amount(200, "$"); // 200 $
amount(200, "GBP"); // 200 £
amount(200, "GBP", true); // 200,00 £
Explanation
The amount() function takes 3 arguments, a number, a currency with a default value of EUR. And last but not least, a boolean conditioning the result as an amount with 2 decimal places or round.
The amount() function then proceeds as follow:
- The first parameters is either parsed or converted into a Number type thanks to the [Number() function] which is almost equivalent to unary plus (+x) but allows in my opinion for a better understanding. Beware of parseInt() which converts empty strings to NaN. If you're looking for a conversion table.
let value;
value = Number(false) || 0; // 0
value = Number("test") || 0; // 0
value = Number("-1000") || 0; // -1000
- The value is then converted to a string with the given rounding.
let stringified_value = (Number(1000) || 0).toFixed(0); // '1000'
stringified_value = (Number(1000) || 0).toFixed(2); // '1000.00'
- In case of a negative number, spaces out the number from the minus in order to properly format it down the line.
const spaced_out_neg_value = stringified_value.replace(/-/g, "-\u00a0"); // '- 1000.00'
- Properly formatting the value spacing out every third character.
// Space out every third character
const formatted_neg_value = spaced_out_neg_value.replace(
/(\d)(?=(\d{3})+(\.|$))/g,
"$1\u00a0"
); // '- 1 000.00'
- Replaces the dot by a comma the suffix the value with the currency given as second parameter.
const comma_formatted_neg_value = formatted_neg_value.replace(".", ","); // '- 1 000,00'
const currency = "EUR";
const amount =
comma_formatted_neg_value +
("\u00a0" +
({
EUR: "€",
USD: "$",
GBP: "£",
}[currency] || currency)); // '- 1 000,00 €'
What if we pass an unreferenced currency? Or if we pass null by accident? Let's try to isolate this behaviour in an independent function.
const add_currency = (value, currency) => {
return (
value +
(currency
? "\u00a0" +
({
EUR: "€",
USD: "$",
GBP: "£",
}[currency] || currency)
: "")
);
};
add_currency("1 000,00", "USD"); // '1 000,00 $'
add_currency("1 000,00", "¥"); // '1 000,00 ¥'
add_currency("1 000,00", "curry"); // '1 000,00 curry'
add_currency("1 000,00", null); // '1 000,00'
As you probably noticed any value can be passed as second parameter but for optimal use it should be added to the values currently supported ({EUR:"€", USD:"$", GBP:"£"})
Conclusion
The final snippet in a concise expression:
const amount = (value, currency = "€", long) => {
return (
(Number(value) || 0)
.toFixed(long ? 2 : 0)
.replace(/-/g, "-\u00a0")
.replace(/(\d)(?=(\d{3})+(\.|$))/g, "$1\u00a0")
.replace(".", ",") +
(currency
? "\u00a0" +
({
EUR: "€",
USD: "$",
GBP: "£",
}[currency] || currency)
: "")
);
};
Top comments (0)