Ho un semplice EditText
, che consente all'utente di inserire un numero come 45.60
(esempio per dollaro americano). poi ho formattare questo numero utilizzando il seguente metodo:NumberFormat.parse() non riesce per alcune stringhe di valuta
public String format() {
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.getDefault());
return formatter.format(amount.doubleValue());
}
E sul mio telefono Android, la lingua è impostata su Inglese (Stati Uniti) - da qui il Locale.getDefault()
dovrebbe restituire il locale degli Stati Uniti (e lo fa).
Ora il testo di modifica viene aggiornato correttamente a: $45.60
(quindi la formattazione del numero inserito funziona).
Tuttavia, se si tenta di analizzare la stringa sopra "$45.60"
utilizzando il seguente metodo:
NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
Number result = numberFormat.parse("$45.60");
non riesce con:
java.lang.IllegalArgumentException: Failed to parse amount $45.60 using locale en_US.
Se ho impostato il mio telefono a Inglese/Regno Unito, la formattazione di questa "45.60"
a "£45.60"
funziona correttamente (come per gli Stati Uniti), tuttavia l'analisi "£45.60"
non riesce, proprio come avviene per il campione statunitense sopra riportato.
Tuttavia, se si imposta il telefono in tedesco (Germania), la formattazione "45,60"
in "45,60€"
funziona correttamente e l'analisi "45,60€"
funziona correttamente!
L'unica differenza che vedo tra queste tre valute: l'euro viene aggiunto all'importo, mentre il dollaro e la sterlina sono preposti all'importo.
Qualcuno ha un'idea, perché lo stesso codice funziona per euro, ma non per sterlina e dollaro? Mi sto perdendo qualcosa?
Ho anche creato un test di unità, di riprodurre il problema:
public void testCreateStringBased() throws Exception {
// For German locale
CurrencyAmount amount = new CurrencyAmount("25,46€", Locale.GERMANY);
assertEquals(25.46, amount.getAsDouble());
// For French locale
amount = new CurrencyAmount("25,46€", Locale.FRANCE);
assertEquals(25.46, amount.getAsDouble());
// For US locale
amount = new CurrencyAmount("$25.46", Locale.US);
assertEquals(25.46, amount.getAsDouble());
// For UK locale
amount = new CurrencyAmount("£25.46", Locale.UK);
assertEquals(25.46, amount.getAsDouble());
}
CurrencyAmount
avvolge in pratica il codice che ho postato per analizzare le stringhe di valute, la differenza che accetta il locale data invece della localizzazione predefinita. Nell'esempio precedente, il test ha esito positivo per le impostazioni internazionali di GERMANIA e FRANCIA, ma non riesce per le impostazioni internazionali per Stati Uniti e Regno Unito.
Non lo definirei "dolorosamente amatoriale". È un caso d'uso comune, specialmente quando si analizza l'input di EditText. Ho anche considerato di imporre il formato corretto (w/currency sign) direttamente su EditText (usando TextWatcher), ma alla fine uso questa soluzione come meno intrusiva per l'utente. Grazie. – pkk