Hi there, is there any KMM lib for currency format...
# multiplatform
a
Hi there, is there any KMM lib for currency formatting in a localised manner? Smth like below
Copy code
double money = 100.1;
NumberFormat formatter = NumberFormat.getCurrencyInstance();
String moneyString = formatter.format(money);
System.out.println(moneyString);
s
There is this library: https://github.com/fluidsonic/fluid-currency. I found it at https://github.com/terrakok/kmp-awesome which is a great place to find kmp libraries
a
This library just gives the mapping. https://kotlinlang.slack.com/archives/C3PQML5NU/p1718630186465909?thread_ts=1679305407.002009&cid=C3PQML5NU How can format string using this lib?
s
It's possible that something like this doesn't exist yet for KMP. If you are doing it for Java it is already almost half of the implementation to create a library. Adding an implementation for apple and another for JS would be almost the whole thing
a
Hmmm makes sense.. seems like need to do it myself. thanks
s
@Atul Gupta How did you solve this problem? I have the exact same requirement. My ios side knowledge is limited to come up with an expect/actual style solution.
I could successfully do it with the
expect/actual
route.
Copy code
iosMain

import platform.Foundation.NSLocale
import platform.Foundation.NSNumber
import platform.Foundation.NSNumberFormatter
import platform.Foundation.NSNumberFormatterCurrencyStyle

private val formatter = NSNumberFormatter().apply {
    locale = NSLocale(localeIdentifier = "DE")
    currencyCode = "eur"
    numberStyle = NSNumberFormatterCurrencyStyle
}
actual fun parseFormattedStringToCents(formattedAmount: String): BigInteger {
    return BigInteger(formatter.numberFromString(formattedAmount)?.longValue ?: 0L)
}

actual fun formatMoney(amount: Double): String {
    val number = NSNumber(amount)
    return formatter.stringFromNumber(number) ?: ""
}

-----------------------------------------------------------
commonMain


import com.ionspin.kotlin.bignum.integer.BigInteger

const val defaultFractionDigits = 2

object MoneyFormatter {

    private fun format(value: Double?, forceSign: Boolean = false, forceNegativeSignForZero: Boolean = false): String {
        if (value == null) {
            return ""
        }
        val valueAsString = formatMoney(value)

        return if (value > 0 && forceSign) {
            "+$valueAsString"
        } else if (forceNegativeSignForZero && value.let { it == 0.0}) {
            "-$valueAsString"
        } else {
            valueAsString
        }
    }
    
    fun formatCents(valueInCents: BigInteger) = format(valueInCents.doubleValue() / getFractionDivider().intValue())

    fun parseToCents(formattedMoneyString: String): BigInteger = parseFormattedStringToCents(formattedMoneyString)

    private fun getFractionDivider(): BigInteger {
        var fractionDigits = defaultFractionDigits
        if (fractionDigits < 1) fractionDigits = 0
        return BigInteger.TEN.pow(fractionDigits)
    }
}

expect fun parseFormattedStringToCents(formattedAmount: String): BigInteger
expect fun formatMoney(amount: Double): String

-----------------------------------------------------------------------------------------------
androidMain

import java.text.DecimalFormat
import java.text.NumberFormat
import java.util.Locale

private val decimalFormat: DecimalFormat = NumberFormat.getCurrencyInstance(Locale.GERMANY) as DecimalFormat
actual fun parseFormattedStringToCents(formattedAmount: String): BigInteger =
    BigInteger(decimalFormat.parse(formattedAmount)?.toLong() ?: 0L)

actual fun formatMoney(amount: Double): String =
    decimalFormat.format(amount)
Also, posted it here: https://kotlinlang.slack.com/archives/C3PQML5NU/p1742498505316619?thread_ts=1742424885.673259&amp;cid=C3PQML5NU
a
Hi In my case I just create a common mapping like shown in the image and skipped the formatting for now
487 Views