I got a bug report from a Swedish user saying that our Swedish currency was using the wrong decimal separator.
NumberFormat enUS = NumberFormat.getCurrencyInstance(Locale.US);
NumberFormat enGB = NumberFormat.getCurrencyInstance(Locale.UK);
NumberFormat svSE = NumberFormat.getCurrencyInstance(new Locale("sv", "SE"));
double cost = 1020d;
String fmt = "en_US: %s en_GB %s sv_SE %s";
String text = String.format(fmt, enUS.format(cost), enGB.format(cost), svSE.format(cost));
Log.e("Format", text);
> Format﹕ en_US: $1,020.00 en_GB £1,020.00 sv_SE 1 020:00 kr
They say that the format should be "1 020,00 kr". When I inspect the format object, it looks like it has decimalSeparator of "," in the symbols table, but a "monetarySeparator" of ":".
Does anyone know if : is actually correct, whether this is a bug in Android/java, or any sort of workaround?
It's like your user says: In Swedish thousand separator is white space " " and decimal separator is comma "," and currency symbol "kr" (Krona). So colon ":" is definitely wrong.
You can check it here too: http://www.localeplanet.com/java/sv-SE/
What Java version are you using? It works well on my desktop 1.6.0_13
-- update --
It seems that on Android there's a bug, but you can go around the bug by using the DecimalFormatSymbols like this:
DecimalFormat svSE = new DecimalFormat("#,###.00");
DecimalFormatSymbols symbols = new DecimalFormatSymbols(new Locale("sv", "SE"));
symbols.setDecimalSeparator(',');
symbols.setGroupingSeparator(' ');
svSE.setDecimalFormatSymbols(symbols);
This prints the correct separators in Android as well.
Related
I am new in Android development and i am stuck at a place. I want to format my currency, I am setting to show without decimal places and with commas.
Example: right now it's showing like 23000.00. But I want the currency like 23,000; how can I do that?
I tried the formatter classes but that doesn't help me.
This is how it's set now.
public class CurrencyFormatter {
public static String setsymbol(BigDecimal data, String currency_symbol)
{
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.ENGLISH);
format.setCurrency(Currency.getInstance(currency_symbol));
String result=data+" "+" دينار";
return result;
}
}
I expect output to be (arabic text)23,000 instead of (arabic test)23000.00
Basically, you need a currency formatter object.
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(currentLocale);
After that you can format an amount of money:
Double currencyAmount = new Double(23000.00);
String formattedOutput = currencyFormatter.format(currencyAmount);
There are more options and explanations available here on Oracle's reference document: https://docs.oracle.com/javase/tutorial/i18n/format/numberFormat.html
check this
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.getDefault());
format.setCurrency(Currency.getInstance("USA"));
String result = format.format(1234567.89);
This is the format set of usa you can change with your country code
reference check description here
Try this, it will show in this format 23,000 without decimal points, It will show thousand separator in the number.
String result = null;
try {
// The comma in the format specifier does the trick
result = String.format("%,d", Long.parseLong(data)); // use this result variable where you want to use.
result = result + " " + " دينار"; // to append arabic text, do as you were doing before.
} catch (NumberFormatException e) {
}
I have an Android application which does some basic mathematics.
Example
try {
NumberFormat nf = NumberFormat.getNumberInstance();
DecimalFormat df = (DecimalFormat) nf;
a = Float.parseFloat(vw3.getText().toString());
f = Float.parseFloat(vw5.getText().toString());
c = a / 100;
d = c * 1.036f;
e = f / 100;
g = e * 1.24f;
h = d + g;
String str1 = String.valueOf(df.format(h));
vw7.setText(str1);
} catch (NumberFormatException f) {
a = (0);
}
}
When the user is in the USA the calculations work fine and format fine. Well as you would expect. The 1,000.00 format where the grouping is by comma and separator is by decimal point. When a user is in France, the grouping is different and the separator is also different. Using the 1,000.00 example, in France the number would be formatted like this 1 000,00. A space is the grouping separator and the comma is the decimal separator. This causes a problem when you try and run a calculation and you will get a NumberFromatException (NFE). And I anticipated a NFE issue and catch it and replace the possible cause with the correct number. However, replacing any comma with a space and any period with a comma will also produce a NFE.
Example
try {
NumberFormat nf = NumberFormat.getNumberInstance();
DecimalFormat df = (DecimalFormat) nf;
a = Float.parseFloat(vw3.getText().toString().replace(",",""));
f = Float.parseFloat(vw5.getText().toString().replace(",",""));
c = a / 100;
d = c * 1.036f;
e = f / 100;
g = e * 1.24f;
h = d + g;
String str1 = String.valueOf(df.format(h));
vw7.setText(str1);
} catch (NumberFormatException f) {
a = (0);
}
}
EDIT - As suggested by Peter O. I have tried parsing the number with a locale aware means.
Example
NumberFormat.getNumberInstance().parse(string);
Or
NumberFormat df = NumberFormat.getNumberInstance();
String value = "10,40 €";
Number valueParsed = df.parse(value);
vw7.setText(valueParsed);
Will produce a "Bad Class" illegalargument.
I am looking for a solution to where I can do the calculations in an acceptable manner within the apps programming regardless of the locale and then later format the results to the locale. The question could be or is, do you force a locale for your calculations and then format the results for the locale?
If this is the code you are using and your strings will have the currency symbol. In this case € the EURO symbol.
Your example:
NumberFormat df = NumberFormat.getNumberInstance();
String value = "10,40 €";
Number valueParsed = df.parse(value);
vw7.setText(valueParsed);
so that value always has a currency symbol you need to use
NumberFormat df= NumberFormat.getCurrencyInstance();
instead of the .getNumberInstance(). This worked on my system which is currently set so that the € symbols is the default currency symbol. You will have to try it on a system that has the $ currency symbol in order to verify that it works there, also.
The below code (which is in JODA) prints: €12,23
String formatAmount = new MoneyFormatterBuilder().
appendCurrencySymbolLocalized().
appendAmountLocalized().
toFormatter().
withLocale(new Locale("es", "ES")).
print(Money.of(CurrencyUnit.EUR, 12.23));
System.out.print(formatAmount);
The below code prints: 12,23 €
String formatAmount = NumberFormat.
getCurrencyInstance(new Locale("es", "ES")).
format(amount);
System.out.print(formatAmount);
Can someone tell me which one is correct and why both the libraries print differently?
While testing on an Android emulator, I came across an inconsistency between the formatted strings produced by a NumberFormat instance and it's reported currency symbol.
I start by setting up a localized currency formatter like so:
// displayLocale is af_NA
DecimalFormat df = (DecimalFormat)
NumberFormat.getCurrencyInstance(displayLocale);
// currency is USD
df.setCurrency(currency); // USD localized for af_NA
Then I use it to format a value. The result of invoking:
df.format(1)
is "$1". This might not seem obviously wrong, but when I check the details of the formatter, things dont add up. Invoking:
df.getDecimalFormatSymbols().getCurrencySymbol()
yields "USD" and not the expected "$"...what!? Even stranger, I've yet to find a physical device that I can replicate the issue on. Tests running under Robolectric don't exhibit this behavior either.
Has anybody else come across this behavior before and if so, any idea what's causing it? And finally, is this behavior that might be encountered on physical devices or is it purely an AVD thing?
UPDATE:
Here's a method you can call from any Activity to check for and print out any offending formatters:
void checkFormatters() {
Currency USD = Currency.getInstance(Locale.US);
Money oneDollar = new Money(BigDecimal.ONE, USD);
for(Locale locale : Locale.getAvailableLocales()) {
DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
df.setCurrency(USD);
String currencySymbol = df.getDecimalFormatSymbols().getCurrencySymbol();
String localizedDollarString = CurrencyUtils.getPrettyCurrencyString(locale, oneDollar);
if(!localizedDollarString.contains(currencySymbol)) {
Log.w(TAG, locale.getDisplayName() + ": Expected localized dollar string [" + localizedDollarString +
"] to contain currency symbol [" + currencySymbol +
"]");
}
}
}
If the device you're testing on has the issue then you'll see results like these:
Uzbek (LATN): Expected localized dollar string [$ 1] to contain currency symbol: [US$]
Uzbek (Uzbekistan,UZ): Expected localized dollar string [$ 1] to contain currency symbol: [US$]
I am trying to format my (usually large) numeric output with space as thousands separator using the following code:
final String PATTERN = "#,##0";
int value1 = Integer.MAX_VALUE;
int value2 = 0;
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setGroupingSeparator(' ');
DecimalFormat df = new DecimalFormat(PATTERN, dfs);
System.out.println("`" + df.format(value1) + "`");
System.out.println("`" + df.format(value2) + "`");
However, which leaves me very confused, the output is:
`2 147 483 647`
``
Please, what is the proper pattern to achieve my desired result:
`2 147 483 647`
`0`
As the good people have already responded in the comments, the pattern is correct and produces the desired result.
The problematic part has been just one step away. Assuming code in the question, then if df.format(getNumber()); fails in #getValue(), the #format() is never executed, which (in my code) eventually resulted in empty string in the user interface and my confusion.