diff options
Diffstat (limited to 'taler-kotlin-android')
-rw-r--r-- | taler-kotlin-android/src/main/java/net/taler/common/Amount.kt | 48 | ||||
-rw-r--r-- | taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt | 46 |
2 files changed, 69 insertions, 25 deletions
diff --git a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt index d6188cf..1652056 100644 --- a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt +++ b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt @@ -23,6 +23,7 @@ import kotlinx.serialization.Serializer import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import java.text.DecimalFormat +import java.text.DecimalFormatSymbols import java.text.NumberFormat import kotlin.math.floor import kotlin.math.pow @@ -214,32 +215,39 @@ public data class Amount( fun toString( showSymbol: Boolean = true, negative: Boolean = false, + symbols: DecimalFormatSymbols = DecimalFormat().decimalFormatSymbols, ): String { - val symbols = DecimalFormat().decimalFormatSymbols - - val format = if (showSymbol) { - NumberFormat.getCurrencyInstance() - } else { - // Make sure monetary separators are the ones used! - symbols.decimalSeparator = symbols.monetaryDecimalSeparator - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - symbols.groupingSeparator = symbols.monetaryGroupingSeparator + // We clone the object to safely/cleanly modify it + val s = symbols.clone() as DecimalFormatSymbols + val amount = (if (negative) "-$amountStr" else amountStr).toBigDecimal() + + // No currency spec, so we render normally + if (spec == null) { + val format = NumberFormat.getInstance() + format.maximumFractionDigits = MAX_FRACTION_LENGTH + format.minimumFractionDigits = 0 + if (Build.VERSION.SDK_INT >= 34) { + s.groupingSeparator = s.monetaryGroupingSeparator } + s.decimalSeparator = s.monetaryDecimalSeparator + (format as DecimalFormat).decimalFormatSymbols = s - NumberFormat.getInstance() + val fmt = format.format(amount) + return if (showSymbol) "$fmt $currency" else fmt } - if (spec != null) { - symbols.currencySymbol = spec.symbol(this) - format.maximumFractionDigits = spec.numFractionalNormalDigits - format.minimumFractionDigits = spec.numFractionalTrailingZeroDigits - } else { - symbols.currencySymbol = currency + // There is currency spec, so we can do things right + val format = NumberFormat.getCurrencyInstance() + format.maximumFractionDigits = spec.numFractionalNormalDigits + format.minimumFractionDigits = spec.numFractionalTrailingZeroDigits + s.currencySymbol = spec.symbol(this) + (format as DecimalFormat).decimalFormatSymbols = s + + val fmt = format.format(amount) + return if (showSymbol) fmt else { + // We should do better than manually removing the symbol here + fmt.replace(s.currencySymbol, "").trim() } - - (format as DecimalFormat).decimalFormatSymbols = symbols - - return format.format((if (negative) "-$amountStr" else amountStr).toBigDecimal()) } override fun compareTo(other: Amount): Int { diff --git a/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt b/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt index 7072426..e7fb273 100644 --- a/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt +++ b/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt @@ -16,10 +16,12 @@ package net.taler.common +import android.os.Build import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test +import java.text.DecimalFormatSymbols import kotlin.random.Random class AmountTest { @@ -41,7 +43,6 @@ class AmountTest { assertEquals("TESTKUDOS", amount.currency) assertEquals(23, amount.value) assertEquals((0.42 * 1e8).toInt(), amount.fraction) - assertEquals("23.42 TESTKUDOS", amount.toString()) str = "EUR:500000000.00000001" amount = Amount.fromJSONString(str) @@ -49,7 +50,6 @@ class AmountTest { assertEquals("EUR", amount.currency) assertEquals(500000000, amount.value) assertEquals(1, amount.fraction) - assertEquals("500000000.00000001 EUR", amount.toString()) str = "EUR:1500000000.00000003" amount = Amount.fromJSONString(str) @@ -57,14 +57,51 @@ class AmountTest { assertEquals("EUR", amount.currency) assertEquals(1500000000, amount.value) assertEquals(3, amount.fraction) - assertEquals("1500000000.00000003 EUR", amount.toString()) } @Test fun testToString() { + val symbols = DecimalFormatSymbols.getInstance() + symbols.decimalSeparator = '.' + symbols.groupingSeparator = ',' + symbols.monetaryDecimalSeparator = '.' + if (Build.VERSION.SDK_INT >= 34) { + symbols.monetaryGroupingSeparator = ',' + } + + val spec = CurrencySpecification( + name = "Bitcoin", + numFractionalInputDigits = 8, + numFractionalNormalDigits = 8, + numFractionalTrailingZeroDigits = 0, + altUnitNames = mapOf( + 0 to "₿", + // TODO: uncomment when units get implemented + // and then write tests for units, please +// -1 to "d₿", +// -2 to "c₿", +// -3 to "m₿", +// -6 to "µ₿", +// -8 to "sat", + ), + ) + Amount.fromString("BITCOINBTC", "0.00000001").let { amount -> - assertEquals("0.00000001 BITCOINBTC", amount.toString()) + // Only the raw amount assertEquals("0.00000001", amount.amountStr) + + // The amount without currency spec + assertEquals("0.00000001 BITCOINBTC", amount.toString(symbols = symbols)) + assertEquals("0.00000001", amount.toString(symbols = symbols, showSymbol = false)) + assertEquals("-0.00000001 BITCOINBTC", amount.toString(symbols = symbols, negative = true)) + assertEquals("-0.00000001", amount.toString(symbols = symbols, showSymbol = false, negative = true)) + + // The amount with currency spec + val withSpec = amount.withSpec(spec) + assertEquals("₿0.00000001", withSpec.toString(symbols = symbols)) + assertEquals("0.00000001", withSpec.toString(symbols = symbols, showSymbol = false)) + assertEquals("-₿0.00000001", withSpec.toString(symbols = symbols, negative = true)) + assertEquals("-0.00000001", withSpec.toString(symbols = symbols, showSymbol = false, negative = true)) } } @@ -76,7 +113,6 @@ class AmountTest { assertEquals(str, amount.toJSONString()) assertEquals("TESTKUDOS123", amount.currency) assertEquals(maxValue, amount.value) - assertEquals("$maxValue.99999999 TESTKUDOS123", amount.toString()) // longer currency not accepted assertThrows<AmountParserException>("longer currency was accepted") { |