I'm trying to format a double variable to a price string (example: €59,00) using NumberFormat
Here is the method I written:
private String formatValue (double price){
NumberFormat f = NumberFormat.getCurrencyInstance(Locale.ITALIAN);
String value = f.format(new BigDecimal(price));
return value;
}
then, I write the returned value in a pdf field using iText library.
form.setField("value", formatValue(price));
Now, when I open the generated pdf in a browser's pdf viewer (like chrome or firefox), the field looks like:
€59,00
but when I open it in adobe reader, or I try to physically print, it appears like
¤59,00.
If I open the variable value in debug, I see the string formatted as ¤59,00.
What I'm doing wrong?
I solved using DecimalFormat instead NumberFormat, and passing the € symbol in utf-8 encode (an input by mwhs [thanks])
private String formatValue (double price){
DecimalFormat formatter = new DecimalFormat("\u20ac0.00");
String value = formatter.format(price);
return value;
}
You may be using separate encoding. Browsers may be using UTF-8, Whereas adobe reader may be using ANSI or another localization of UTF. (Note these are not necessarily the encoding they use, just an example) so check your preferences, and try again.
You can use the actual UTF-8 Euro symbol which makes the code more readable.
private static final DecimalFormat EURO_FORMAT = new DecimalFormat("€0.00");
private String formatValue (double price){
return EURO_FORMAT.format(price);
}
But the java.util.NumberFormat is a better choice since you can use the Locale for the correct number format. In France, Germany and the Netherlands the comma is used instead of the decimal point before the cents. But the format for thousands is different. See below for an example:
public class NumberFormatLocaleExample {
public static void main(final String[] args) {
double price = 1249.69;
System.out.println(formatValueGermany(price));
System.out.println(formatValueFrance(price));
}
private static final NumberFormat EURO_FORMAT_GER = NumberFormat.getCurrencyInstance(Locale.GERMAN);
private static String formatValueGermany(double price){
return String.format("€%s", EURO_FORMAT_GER.format(price));
}
private static final NumberFormat EURO_FORMAT_FRANCE = NumberFormat.getCurrencyInstance(Locale.FRENCH);
private static String formatValueFrance(double price){
return String.format("€%s", EURO_FORMAT_FRANCE.format(price));
}
}
Problem is the Locale: you are using ITALIAN, correct would be ITALY, because ITALIAN may refer to other countries where they speak Italian, but ITALY means the country with its units including the currency.
private String formatValue (double price){
NumberFormat f = NumberFormat.getCurrencyInstance(Locale.ITALY);
String value = f.format(new BigDecimal(price));
return value;
}
Would give you the right Euro-symbol. Same is true for GERMAN vs. GERMANY or FRENCH vs. FRANCE btw.
Related
I have a sentence in modal e.g. "Your balance is 29,2 euro" and I need to get a number and store it. But a number is dynamic. So don't know the exact value. It can be integer as well as decimal.
And then I need to compare this value (the one which has been stored) with the value on next page.
Thank you for any help :)
Welcome to SO :)
Given that your string is quite static and you want to find a value inside it, I'd recommend you use Apache Commons' substringBetween. If you don't want to add an additional dependency then you could implement this method yourself, it looks something like this:
public static String substringBetween(String initial, String open, String close) {
int start = str.indexOf(open) + open.length();
int end = str.indexOf(close, start);
return str.substring(start, end);
}
Then the following issue you'd have is that separating decimals by comma is not Java's standard, so 29,2 won't be resolved by Double.valueOf or Double.parseDouble. You will need to either:
Replace comma with dot, this can be achieved by using str.replaceAll(",", ".")
Use a NumberFormat. For example, default NumberFormat for France Locale is using a comma to separate decimals.
A final solution will look like this:
public static void main(String[] args) throws ParseException {
String initialString = "Your balance is 29,2 euro";
double doubleValue = parseAsDouble(findValue(initialString));
System.out.println(doubleValue);
}
private static String findValue(String initial) {
return StringUtils.substringBetween(initial, "Your balance is ", " euro");
}
private static double parseAsDouble(String value) throws ParseException {
return NumberFormat.getInstance(Locale.FRANCE)
.parse(value)
.doubleValue();
}
As mentioned earlier, you could change the implementation of findValue to use substring or regex and the implementation of parseAsDouble to use Double.parseDouble after replacing comma with dot.
In Java and Kotlin there is an API that can used to show a time without having to create a string resource.
In the example line of code below, this value allows the time of 8 hours after midnight to automatically chnage the way its displayed depending on the device locale.
val timeCustom = LocalTime.of(8, 0)
Is there something similar that can be used for a decimal number, where the value automatically uses a specific demical symbol dpending on the locale? (. or ,).
For example, to describe the height of something (e.g. 5 point 2 metres):
val decimalNumber = Decimal.of(5,2)
Is there something like this available?
You can use Locale.getDefault() e.g.
import java.text.NumberFormat;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
Locale currentLocale = Locale.getDefault();
Integer quantity = 123456;
Double amount = 345987.246;
NumberFormat numberFormatter;
String quantityOut;
String amountOut;
numberFormatter = NumberFormat.getNumberInstance(currentLocale);
quantityOut = numberFormatter.format(quantity);
amountOut = numberFormatter.format(amount);
System.out.println(quantityOut);
System.out.println(amountOut);
}
}
Output:
123,456
345,987.246
I have the double value 1400.0 and now I want to format this value into 1.400,00 in Java.
currently I do:
double doubleValue = 1400.0
String pattern = "0.00";
DecimalFormat format = (DecimalFormat)NumberFormat.getNumberInstance(Locale.GERMAN)
format .applyPattern(pattern);
// will be 1400,00 and not 1.400,00
String formattedValue = format.format(doubleValue);
What am I missing?
Try:
String pattern = "#,##0.00";
This pattern tells a DecimalFormat to add the grouping character to the given number.
Edit: Originally I wrote this with zeros, but this would actually create extra zeros for small numbers. Use the # pattern where you don't want initial zeros.
You can try something like this:
class MyClass {
public static void main(String[] args) {
double doubleValue = 74637.96;
Locale locale = Locale.GERMAN;
String string = NumberFormat.getNumberInstance(locale).format(doubleValue);
System.out.println(string);
}
}
and the output will be:
74.637,96
GermanFormat
How can I get a NumberFormat (or DecimalFormat) instance corresponding to an ISO 4217 currency code (such as "EUR" or "USD") in order to format prices correctly?
Note 1: The problem I'm having is that the NumberFormat/DecimalFormat classes have a
getCurrencyInstance(Locale locale) method but I can't figure out how
to get to a Locale object from an ISO 4217 currency code.
Note 2: There is also a java.util.Currency class which has a getInstance(String currencyCode) method (returning the Currency
instance for a given ISO 4217 currency code) but again I can't figure
out how to get from a Currency object to a NumberFormat
instance...
I'm not sure I understood this correctly, but you could try something like:
public class CurrencyTest
{
#Test
public void testGetNumberFormatForCurrencyCode()
{
NumberFormat format = NumberFormat.getInstance();
format.setMaximumFractionDigits(2);
Currency currency = Currency.getInstance("USD");
format.setCurrency(currency);
System.out.println(format.format(1234.23434));
}
}
Output:
1,234.23
Notice that I set the maximum amount of fractional digits separately, the NumberFormat.setCurrency doesn't touch the maximum amount of fractional digits:
Sets the currency used by this number format when formatting currency
values. This does not update the minimum or maximum number of fraction
digits used by the number format.
Locale can be used both to get the standard currency for the Locale and to print any currency symbol properly in the locale you specify. These are two distinct operations, and not really related.
From the Java Internationalization tutorial, you first get an instance of the Currency using either the Locale or the ISO code. Then you can print the symbol using another Locale. So if you get the US Currency from the en_US Locale, and call getSymbol() it will print "$". But if you call getSymbol(Locale) with the British Locale, it will print "USD".
So if you don't care what your current user's locale is, and you just care about the currencies, then you can ignore the Locale in all cases.
If you care about representing the currency symbol correctly based on your current user, then you need to get the Locale of the user specific to the user's location.
The mapping is sometimes one to many... Like the euro is used in many countries (locales)...
Just because the currency code is the same the format might be different as this example shows:
private static Collection<Locale> getLocalesFromIso4217(String iso4217code) {
Collection<Locale> returnValue = new LinkedList<Locale>();
for (Locale locale : NumberFormat.getAvailableLocales()) {
String code = NumberFormat.getCurrencyInstance(locale).
getCurrency().getCurrencyCode();
if (iso4217code.equals(code)) {
returnValue.add(locale);
}
}
return returnValue;
}
public static void main(String[] args) {
System.out.println(getLocalesFromIso4217("USD"));
System.out.println(getLocalesFromIso4217("EUR"));
for (Locale locale : getLocalesFromIso4217("EUR")) {
System.out.println(locale + "=>" + NumberFormat.getCurrencyInstance(locale).format(1234));
}
}
Output
[en_US, es_US, es_EC, es_PR]
[pt_PT, el_CY, fi_FI, en_MT, sl_SI, ga_IE, fr_BE, es_ES, de_AT, nl_NL, el_GR, it_IT, en_IE, fr_LU, nl_BE, ca_ES, sr_ME, mt_MT, fr_FR, de_DE, de_LU]
pt_PT=>1.234,00 €
el_CY=>€1.234,00
fi_FI=>1 234,00 €
en_MT=>€1,234.00
sl_SI=>€ 1.234
ga_IE=>€1,234.00
fr_BE=>1.234,00 €
es_ES=>1.234,00 €
de_AT=>€ 1.234,00
nl_NL=>€ 1.234,00
el_GR=>1.234,00 €
it_IT=>€ 1.234,00
en_IE=>€1,234.00
fr_LU=>1 234,00 €
nl_BE=>1.234,00 €
ca_ES=>€ 1.234,00
sr_ME=>€ 1.234,00
mt_MT=>€1,234.00
fr_FR=>1 234,00 €
de_DE=>1.234,00 €
de_LU=>1.234,00 €
For completeness, though I've never used it, you might want to give Joda Money a try. If it's as good as Joda-Time, it probably is easier and more powerful than the standard JDK stuff.
Try the following method:
private static NumberFormat getNumberFormat(String currencyCode)
{
Currency currency = Currency.getInstance(currencyCode);
Locale[] locales = NumberFormat.getAvailableLocales();
for (Locale locale : locales)
{
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(locale);
if (numberFormat.getCurrency() == currency)
return numberFormat;
}
return null;
}
public class PriceHelper {
public static String formatPrice(Context context, String currencyCode,
double price) {
if (price == 0) {
return context.getString(R.string.free);
}
Currency currency = Currency.getInstance(currencyCode);
NumberFormat format = NumberFormat.getCurrencyInstance();
format.setCurrency(currency);
return format.format(price);
}
}
How do I convert a double value with 10 digits for e.g 9.01236789E9 into a string 9012367890 without terminating any of its digits ?
I tried 9.01236789E9 * Math.pow(10,9) but the result is still double "9.01236789E18"
double d = 9.01236789E9;
System.out.println(BigDecimal.valueOf(d).toPlainString());
While 10 digits should be preservable with no problems, if you're interested in the actual digits used, you should probably be using BigDecimal instead.
If you really want to format a double without using scientific notation, you should be able to just use NumberFormat to do that or (as of Java 6) the simple string formatting APIs:
import java.text.*;
public class Test
{
public static void main(String[] args)
{
double value = 9.01236789E9;
String text = String.format("%.0f", value);
System.out.println(text); // 9012367890
NumberFormat format = NumberFormat.getNumberInstance();
format.setMaximumFractionDigits(0);
format.setGroupingUsed(false);
System.out.println(format.format(value)); // 9012367890
}
}
Try String.format("%20.0f", 9.01236789E9)
Note though it's never an exact value, so "preserving every digit" doesn't really make sense.
You can use it.
String doubleString = Double.toString(inValue)
inValue -----> Described by you.to what position you want to Change double to a string.
In this case, you can also do
double value = 9.01236789E9;
System.out.println((long) value); // prints 9012367890