xatok
xatok

Reputation: 1215

Use Android ICU NumberFormat with only the JVM

Android has the ICU library NumberFormat which allows formatting currencies in different ways, in my specific case I need it as ISOCURRENCYSTYLE. This works great but only works on Android.

Java as its own implementation of NumberFormat with an instance builder called getCurrencyInstance, which internally uses a default currency style and doesn't allow to specify it.

Some of the differences are:

BE_FR | Android: 123,12 EUR |   Java: 123,12 €
BE_NL | Android: EUR 123,12 |   Java: € 123,12
BE_EN | Android: EUR 123.12 |   Java: €123,12
GE_GE | Android: EUR 123.12 |   Java: €123.12
FR_FR | Android: 123,12 EUR |   Java: 123,12 €

Is there a way to get the same Android output but only within the JVM, without using any external library?

Upvotes: 0

Views: 934

Answers (2)

Olivier
Olivier

Reputation: 18067

A solution is to replace the prefix and the suffix of the DecimalFormat with the currency code:

import java.text.*;
import java.util.Locale;

public class Test
{
    public static DecimalFormat geCurrencyFormat(Locale locale)
    {
        DecimalFormat df = (DecimalFormat)NumberFormat.getCurrencyInstance(locale);
        String code = df.getCurrency().getCurrencyCode();
        if(!df.getPositivePrefix().isEmpty())
        {
            df.setPositivePrefix(code + " ");
            df.setNegativePrefix(code + " -");
        }
        if(!df.getPositiveSuffix().isEmpty())
        {
            df.setPositiveSuffix(" " + code);
            df.setNegativeSuffix(" " + code);
        }
        return df;
    }

    public static void test(Locale locale)
    {
        DecimalFormat df = geCurrencyFormat(locale);
        System.out.println(df.format(123.12));
    }

    public static void main(String args[])
    {
      test(new Locale("fr", "BE"));
      test(new Locale("nl", "BE"));
      test(new Locale("en", "GB"));
   }
}

Output:

123,12 EUR
EUR 123,12
GBP 123.12

Upvotes: 1

BryceCicada
BryceCicada

Reputation: 275

Unfortunately not. You can get the three-letter ISO 4217 codes using Currency and hand-craft things like:

Locale locale = Locale.FRANCE;
float amount = 123.1f;
NumberFormat nf = NumberFormat.getInstance(locale);
Currency currency = Currency.getInstance(locale);
String formattedAmount = nf.format(amount) + " " + currency.getCurrencyCode());

However, Android is using ICU code to correctly order the value and units in the currency string. This is not in the standard Java JDKs.

I understand you don't want to use a library, so this is out of scope of the required answer. However, should you choose to use a library, take a look at ICU4J https://unicode-org.github.io/icu/userguide/icu4j/. It includes a NumberFormat with ISOCURRENCYSTYLE matching the Android behaviour.

Upvotes: 0

Related Questions