I am using java.text.MessageFormat
to replace place holders in a template that displays price per unit. Following is the piece of code that does it.
public String format(Object[] arguments, String pattern) {
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(pattern);
return formatter.format(arguments);
}
pattern
is
{0} {1} per {2}
and arguments
are
argument[0] = "USD", argument[1] = BigDecimal(0.0002), argument[2] = "shirt"
I expected the formatter to output
"USD 0.0002 per shirt"
But formatter is reducing the precision and produces
"USD 0 per shirt"
It looks like MessageFormat
is considering just 3 digits after the decimal point. "BigDecimal(0.01)" works as expected.
So is there any property I can tweak to tell the MessageFormat
it should use a certain precision? Changing the pattern
is not an option for me.
I can convert the argument to String
from BigDecimal
before formatting. But that will be my last option.
EDIT:
The limit of 3 decimal points comes from NumberFormat
.
private int maximumFractionDigits = 3;
is there a way we can change this value and make MessageFormat use this?
You can use formats such as {0,number,#.##}
in the pattern.
The Javadoc of MessageFormat has more details if you're interested.
Since you cannot change the pattern, converting the objects to string before-hand would be the only solution though
EDIT: actually I did not realize that the formats could be set programmatically:
public static void main(String[] args) {
Object[] argument = new Object[3];
argument[0] = "USD";
argument[1] = new BigDecimal(0.0002);
argument[2] = "shirt";
System.out.println(format(argument, "{0} {1} per {2}"));
}
public static String format(Object[] arguments, String pattern) {
MessageFormat formatter = new MessageFormat(pattern);
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(7);
for (int i = 0; i < arguments.length; i++) {
if (arguments[i] instanceof BigDecimal) {
formatter.setFormat(i, nf);
}
}
return formatter.format(arguments);
}
This should print: USD 0.0002 per shirt