FULL PRODUCT VERSION :
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+132)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+132, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Darwin sparky.local 15.6.0 Darwin Kernel Version 15.6.0: Thu Jun 23 18:25:34 PDT 2016; root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64
A DESCRIPTION OF THE PROBLEM :
The official locale decimal information for en_ZA (English, South Africa), is to use a comma for a decimal point and a space for a thousand separator. Thus the US/UK number 123,456.78 would be written officially as 123 456,78. However, no one uses the official representation in South Africa. All the internet banking is with the US/UK format 123,456.78. Online shopping is also done with the US/UK format.
Up to now, System.out.printf("%,f", 3.14159) output 3.14159. However, in Java 9, this was changed to output 3,14159.
Whilst this is correct according to the official format, it is not correct according to the common use in the country. No one uses the official format, not even the government gazettes.
The common solution to this problem is to customize the settings in the system properties. For example, I changed the decimal to a dot and the thousand separator to a comma.
Whilst Java 9 is correct according to the official format, it is not correct in that it does not use the user customized settings. These should override the official format.
This is a very serious bug for anyone using Java in South Africa. A transfer of R5125.23 suddenly becomes R512523,00 thus 100x more!!! Since Java is so ubiquitous, it is essential that this bug is fixed in Java 9. Companies absolutely cannot move over to Java 9 until it is repaired. And PLEASE do not backport this to Java 8.
REGRESSION. Last worked in version 8u102
ADDITIONAL REGRESSION INFORMATION:
In Java 8 it worked because the locale information for decimal points was not correct. So it worked accidentally.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the following program:
import java.util.*;
public class MysteryOfTheComma {
public static void main(String... args) throws ReflectiveOperationException {
System.out.println("default=" + Locale.getDefault());
System.out.println("user.language=" + System.getProperty("user.language"));
System.out.println("user.country=" + System.getProperty("user.country"));
System.out.println("user.country.format=" + System.getProperty("user.country.format"));
System.out.printf(Locale.US, "%.3f%n", 3.14159f);
System.out.printf(new Locale("de", "DE"), "%.3f%n", 3.14159f);
System.out.printf("%.3f%n", 3.14159f);
}
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should output
3.142
3,142
3.142
Because that's my configured locale information.
ACTUAL -
It output instead:
3.142
3,142
3,142
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.*;
public class MysteryOfTheComma {
public static void main(String... args) throws ReflectiveOperationException {
System.out.println("default=" + Locale.getDefault());
System.out.println("user.language=" + System.getProperty("user.language"));
System.out.println("user.country=" + System.getProperty("user.country"));
System.out.println("user.country.format=" + System.getProperty("user.country.format"));
System.out.printf(Locale.US, "%.3f%n", 3.14159f);
System.out.printf(new Locale("de", "DE"), "%.3f%n", 3.14159f);
System.out.printf("%.3f%n", 3.14159f);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Stuart Marks found a workaround for this bug. If we start it with the setting:
java -Djava.locale.providers=HOST,CLDR,JRE MysteryOfTheComma
Then it picks up the HOST setting first and only afterwards the official Unicode setting (CLDR)

Comments

JDK now follows CLDR releases for locale data. I'd suggest this problem be reported to http://cldr.unicode.org/index/bug-reports to request a variant of en_ZA locale data.

2016-09-02

With JEP 252 (http://openjdk.java.net/jeps/252 ) , the default locale provider is now CLDR. It was JRE in JDK 8.(https://docs.oracle.com/javase/8/docs/technotes/guides/intl/enhancements.8.html#cldr )
Hence, the observed difference in behavior.
The desired behavior can be achieved by using the java.locale.providers system property, listing the data sources in the preferred order, as has been stated in the workaround section.
Closing as not an issue.