Search code examples
kotlincurrencynumber-formattingdecimalformatcurrency-formatting

Change the currency to a currency formatter


I have the following method to build a currency formatter. There are 2 input fields, the locale and the currency:

    private fun getCurrencyDecimalFormat(locale: Locale, currency: Currency): DecimalFormat {
        val currencyFormat = NumberFormat.getCurrencyInstance(locale) as DecimalFormat
        currencyFormat.positivePrefix = currencyFormat.positivePrefix + " "
        currencyFormat.roundingMode = RoundingMode.DOWN 
        val symbol = currency.getSymbol(locale)
        val decimalFormatSymbols = currencyFormat.decimalFormatSymbols
        decimalFormatSymbols.currencySymbol = symbol
        currencyFormat.decimalFormatSymbols = decimalFormatSymbols
        currencyFormat.isParseBigDecimal = true
        return currencyFormat
    }

And it is called like this:

    val currencyFormat = getCurrencyDecimalFormat(locale, currency)
    return currencyFormat.format(amount)

It works fine when the currency input is the same as the currency of the locale input, so:

  • locale: es_ES, currency: EUR = 0,00 € -> OK
  • locale: en_US, currency: USD = $ 0.00 -> OK

But if we have the following it is wrong:

  • locale: es_ES, currency: USD = 0,00 $ -> KO
  • locale: en_US, currency: EUR = $ 0.00 -> KO

It seems the currency is not set properly... any idea? I'm doing something wrong?


Solution

  • This seems to be due to this line:

    currencyFormat.positivePrefix = currencyFormat.positivePrefix + " "
    

    Positive prefix at this point depends on the currency of the passed locale. If, for example, you invoke your method as getCurrencyDecimalFormat(Locale.US, Currency.getInstance("EUR")), then your currencyFormat is bound to USD at this point (and currencyFormat.positivePrefix results in $).

    Move this line further down, below setting your format symbols. But TBH I'm not even sure why you need it. Having a space after the currency symbol should be locale-dependent and not hardcoded.

    fun getCurrencyDecimalFormat(locale: Locale, currency: Currency): DecimalFormat {
        val currencyFormat = NumberFormat.getCurrencyInstance(locale) as DecimalFormat
    
        currencyFormat.roundingMode = RoundingMode.DOWN
    
        val symbol = currency.getSymbol(locale)
        val decimalFormatSymbols = currencyFormat.decimalFormatSymbols
    
        decimalFormatSymbols.currencySymbol = symbol
    
        currencyFormat.decimalFormatSymbols = decimalFormatSymbols
        currencyFormat.isParseBigDecimal = true
        currencyFormat.positivePrefix = currencyFormat.positivePrefix + " "
    
        return currencyFormat
    }