Formatting monetary amounts with Java Money
Java is very often used to develop big financial systems, yet still the JDK has little or no support for monetary arithmetics, currency conversion, formatting money for different locales etc. There’s only a Currency class which serves as a list of ISO 4217 currencies.
Fortunately we’ve got the JSR-354 standard and Moneta – the reference implementation. It provides us the Martin Fowler’s money pattern along with string formatting and currency repositories.
In this article I will focus on displaying monetary amounts for different currencies, locales and personal preferences.
Basic example: amount and ISO symbol
final Locale[] locales = {
Locale.US,
new Locale("nl", "NL"),
new Locale("pl", "PL")
};
final Money amount = Money.of(12345.67, "USD");
for (Locale locale : locales) {
MonetaryAmountFormat formatter = MonetaryFormats.getAmountFormat(locale);
System.out.println(formatter.format(amount));
}
en_US | nl_NL | pl_PL |
---|---|---|
USD12,345.67 | USD 12.345,67 | 12 345,67 USD |
Amount with a currency symbol
final Locale[] locales = {
Locale.US,
new Locale("nl", "NL"),
new Locale("pl", "PL")
};
final Money amount = Money.of(12345.67, "USD");
for (Locale locale : locales) {
MonetaryAmountFormat formatter = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(locale)
.set(CurrencyStyle.SYMBOL)
.build());
System.out.println(formatter.format(amount));
}
en_US | nl_NL | pl_PL |
---|---|---|
$12,345.67 | USD 12.345,67 | 12 345,67 USD |
The $
currency symbol is displayed only for the United States locale. Other languages do not use it.
Amount with a full currency name
final Locale[] locales = {
Locale.US,
new Locale("nl", "NL"),
new Locale("pl", "PL")
};
final Money amount = Money.of(12345.67, "USD");
for (Locale locale : locales) {
MonetaryAmountFormat formatter = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(locale)
.set(CurrencyStyle.NAME)
.build());
System.out.println(formatter.format(amount));
}
en_US | nl_NL | pl_PL |
---|---|---|
US Dollar12,345.67 | US Dollar 12.345,67 | 12 345,67 US Dollar |
Amount without a thousands separator
final Locale[] locales = {
Locale.US,
new Locale("nl", "NL"),
new Locale("pl", "PL")
};
final Money amount = Money.of(12345.67, "USD");
for (Locale locale : locales) {
MonetaryAmountFormat formatter = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(locale)
.set(AmountFormatParams.GROUPING_SIZES, new int[]{2, 0})
.build());
System.out.println(formatter.format(amount));
}
en_US | nl_NL | pl_PL |
---|---|---|
USD12345.67 | USD 12345,67 | 12345,67 USD |
Grouping sizes are specified starting from the decimal point. In the above example we have two digits after the decimal point, and then we have no more grouping going to the left. Of course other combinations are possible, e.g. {2, 3, 4}
.
Custom pattern
Using a pattern as defined by java.text.DecimalFormat.
final Locale[] locales = {
Locale.US,
new Locale("nl", "NL"),
new Locale("pl", "PL")
};
final Money amount = Money.of(12345.67, "USD");
for (Locale locale : locales) {
MonetaryAmountFormat formatter = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(locale)
.set(AmountFormatParams.PATTERN, "###,###.## ¤")
.build());
System.out.println(formatter.format(amount));
}
en_US | nl_NL | pl_PL |
---|---|---|
12,345.67 USD | 12.345,67 USD | 12 345,67 USD |