JSR-354 MonetaryAmountFormat не работает в двух направлениях для других символов валюты, кроме $, € или £
Вот пример кода, который я использую с Moneta версии 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());
Это должно работать, так как я конвертирую один и тот же объект назад и вперед. Если я не ошибся, и конвертер не является двусторонним для других валют, кроме $, € или £.
Последняя строка вылетает с:
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)
Это происходит, если локаль не связана с одним из $, € или £. Например, этот код будет работать для Locale.US
, но потерпит крах Locale.CHINA
а также с new Locale("pl", "PL")
, Так что это не только проблема с пользовательским Locale
но и статически предопределенные.
Я немного покопался во внутренней упаковке и нашел org.javamoney.moneta.internal.format.CurrencyToken.parse(CurrencyToken.java:196)
, который выглядит как:
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;
Есть ли способ заставить мой код выше работать для валют, отличных от $, € или £?
Я пробовал еще несколько вещей, например, при условии, что Locale.CANADA они также имеют символ валюты $, так что он выполняется без ошибок, но возвращает неверные данные
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());
возврат последней строки USD
вместо CAD
что и делает этот if-else за $. Я думаю, что это также ошибочно предполагает, что символ - валюта - отображение один в один.
1 ответ
Мы работаем над решением проблем, поднятых https://github.com/JavaMoney/jsr354-ri/issues/149.
Ожидайте исправления Moneta для этой и других проблем в ближайшее время.
Вернер