问题
Here is example code that I'm using with Moneta version 1.1:
Locale LANG = Locale.CHINA; // also tried new Locale("pl", "PL");
final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(LANG)
.set(CurrencyStyle.SYMBOL)
.set("pattern", "#,##0.00### ¤")
.build()
);
final String formatted = format.format(Money.of(new BigDecimal("1234.56"), Monetary.getCurrency(LANG)));
System.out.println(formatted);
System.out.println(format.parse(formatted).getNumber());
This should work since I'm converting same object back and forth. Unless I got something wrong and converter is not two-way for other currencies than $, € or £.
The last line crashes with:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid error index > input.length
at javax.money.format.MonetaryParseException.<init>(MonetaryParseException.java:56)
at org.javamoney.moneta.internal.format.AmountNumberToken.parse(AmountNumberToken.java:140)
at org.javamoney.moneta.internal.format.DefaultMonetaryAmountFormat.parse(DefaultMonetaryAmountFormat.java:190)
at test.main(test.java:27)
This happens if provided locale is not associated with one of $, € or £. For instance this code will work for Locale.US, but will crash for Locale.CHINA as well as with new Locale("pl", "PL"). So this is not only problem with custom defined Locale but those statically predefined as well.
I have dug a little into the internal package and found org.javamoney.moneta.internal.format.CurrencyToken.parse(CurrencyToken.java:196), which looks like:
case SYMBOL:
if (token.startsWith("$")) {
cur = Monetary.getCurrency("USD");
context.consume("$");
} else if (token.startsWith("€")) {
cur = Monetary.getCurrency("EUR");
context.consume("€");
} else if (token.startsWith("£")) {
cur = Monetary.getCurrency("GBP");
context.consume("£");
} else {
cur = Monetary.getCurrency(token);
context.consume(token);
}
context.setParsedCurrency(cur);
break;
Is there any way to make my code above work for currencies other than $, € or £?
I have try few more things for instance provided Locale.CANADA they also have $ as currency symbol so it execute without failure but returns wrong data
Locale LANG = Locale.CANADA;
final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(LANG)
.set(CurrencyStyle.SYMBOL)
.set("pattern", "#,##0.00### ¤")
.build()
);
final String formatted = format.format(Money.of(new BigDecimal("1234.56"), Monetary.getCurrency(LANG)));
System.out.println(formatted);
System.out.println(format.parse(formatted).getCurrency().getCurrencyCode());
last line return USD instead of CAD which is what this if-else does for $. I think it also wrongly assumes that symbol - currency is one to one mapping.
回答1:
We're working on a solution, issues raised https://github.com/JavaMoney/jsr354-ri/issues/149.
Expect Moneta patches for this and other issues soon.
Werner
来源:https://stackoverflow.com/questions/40244526/jsr-354-monetaryamountformat-not-working-two-way-for-other-currency-symbols-than