mirror of
https://github.com/corda/corda.git
synced 2024-12-21 22:07:55 +00:00
Amount: add support for basic parsing from text.
This commit is contained in:
parent
bea256caf1
commit
7cac55ca4a
@ -48,6 +48,58 @@ data class Amount<T>(val quantity: Long, val token: T) : Comparable<Amount<T>> {
|
||||
val longQuantity = quantity.movePointRight(currency.defaultFractionDigits).toLong()
|
||||
return Amount(longQuantity, currency)
|
||||
}
|
||||
|
||||
private val currencySymbols: Map<String, Currency> = mapOf(
|
||||
"$" to USD,
|
||||
"£" to GBP,
|
||||
"€" to EUR
|
||||
)
|
||||
private val currencyCodes: Map<String, Currency> by lazy { Currency.getAvailableCurrencies().map { it.currencyCode to it }.toMap() }
|
||||
|
||||
/**
|
||||
* Returns an amount that is equal to the given currency amount in text. Examples of what is supported:
|
||||
*
|
||||
* - 12 USD
|
||||
* - 14.50 USD
|
||||
* - 10 USD
|
||||
* - 30 CHF
|
||||
* - $10.24
|
||||
* - £13
|
||||
* - €5000
|
||||
*
|
||||
* Note this method does NOT respect internationalisation rules: it ignores commas and uses . as the
|
||||
* decimal point separator, always. It also ignores the users locale: $ is special cased to be USD,
|
||||
* £ is special cased to GBP and € is special cased to Euro. Thus an input of $12 expecting some other
|
||||
* countries dollar will not work. Do your own parsing if you need correct handling of currency amounts
|
||||
* with locale-sensitive handling.
|
||||
*
|
||||
* @throws IllegalArgumentException if the input string was not understood.
|
||||
*/
|
||||
fun parseCurrency(input: String): Amount<Currency> {
|
||||
val i = input.filter { it != ',' }
|
||||
try {
|
||||
// First check the symbols at the front.
|
||||
for ((symbol, currency) in currencySymbols) {
|
||||
if (i.startsWith(symbol)) {
|
||||
val rest = i.substring(symbol.length)
|
||||
return fromDecimal(BigDecimal(rest), currency)
|
||||
}
|
||||
}
|
||||
// Now check the codes at the end.
|
||||
val split = i.split(' ')
|
||||
if (split.size == 2) {
|
||||
val (rest, code) = split
|
||||
for ((cc, currency) in currencyCodes) {
|
||||
if (cc == code) {
|
||||
return fromDecimal(BigDecimal(rest), currency)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e: Exception) {
|
||||
throw IllegalArgumentException("Could not parse $input as a currency", e)
|
||||
}
|
||||
throw IllegalArgumentException("Did not recognise the currency in $input or could not parse")
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -23,4 +23,12 @@ class AmountTests {
|
||||
assertEquals(expected, amount.toDecimal())
|
||||
assertEquals(amount, Amount.fromDecimal(amount.toDecimal(), amount.token))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsing() {
|
||||
assertEquals(Amount(1234L, GBP), Amount.parseCurrency("£12.34"))
|
||||
assertEquals(Amount(1200L, GBP), Amount.parseCurrency("£12"))
|
||||
assertEquals(Amount(1000L, USD), Amount.parseCurrency("$10"))
|
||||
assertEquals(Amount(1500000000L, CHF), Amount.parseCurrency("15,000,000 CHF"))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user