1

We found a weird bug in Java. Guess it's from the people who removed the German date format:

Locale.setDefault(Locale.ENGLISH);
System.out.println(Locale.getDefault());
System.out.println(NumberFormat.getInstance().format(0.001));

Locale.setDefault(new Locale("cs", "CZ")); 
System.out.println(Locale.getDefault());
System.out.println(NumberFormat.getInstance().format(0.001));

Take a moment to guess what this code should return. Now take a look at what it returns:

en
0.001
cs_CZ
0

Yes, "0.001" for English and "0" (instead of "0,001") for Czech. Why would that be? The following code gives a hint:

    for (final Locale locale : Locale.getAvailableLocales()) {
        final int maximumFractionDigits = NumberFormat.getInstance(locale).getMaximumFractionDigits();
        if (maximumFractionDigits != 3) {
            System.out.println(locale.getDisplayCountry() + " -> " + maximumFractionDigits);
        }
    }

It returns:

Czech Republic -> 2
Lithuania -> 2

So for some reason maximumFractionDigits is locale specific. Neither we nor the our representative Czechs know why.

All frustration about this random behavior aside: which other fields of the NumberFormat are also locale specific, i.e. have to be initialized each time we need a NumberFormat?

(After spending an entire work day trying to figure this bug out, I'm inclined to ask "why", but that's probably opinion based either way.)

PS. we ran the program with different Java versions. For some reason it seems to work in update 51 and 112, but is broken in update 45, 131, 144, 152 and 161. Java 9 seems to be completely funky.

Stefan S.
  • 3,950
  • 5
  • 25
  • 77
  • *Guess it's from the people who removed the German date format:* Sounds like they broke their Java runtimes. I wouldn't support customized / broken JREs. – Elliott Frisch Mar 08 '18 at 15:10
  • Your code executed in JDK 9 outputs `United States -> 6`. – zlakad Mar 08 '18 at 15:17
  • @ElliottFrisch Who's they? Sun? – Stefan S. Mar 08 '18 at 15:19
  • Also in JDK 9: `Locale.setDefault(new Locale("cs", "CZ")); System.out.println(Locale.getDefault()); cs_CZ System.out.println(NumberFormat.getInstance().format(0.001)); 0,001` – zlakad Mar 08 '18 at 15:22
  • @zlakad We ran it with different Java versions (all Java 8 though), and it behaves differently in each. I added it to the question. – Stefan S. Mar 08 '18 at 15:26
  • I ran it in Java 8 and you're probably right - it's a bug. – zlakad Mar 08 '18 at 15:28
  • @zlakad Thought so. But before I'll go through our million lines of code I'd like to know if I need to set another property as well, so we won't get a value of `minimumFractionDigits=6` for EN next Java update. – Stefan S. Mar 08 '18 at 15:34
  • IDK, it's a question for Oracle... Yep, bugs sucks... – zlakad Mar 08 '18 at 15:38
  • @SteffiS. *Who's they? Sun?* I don't know, who are "the people who removed the German date format"? Was that Sun? – Elliott Frisch Mar 08 '18 at 16:00
  • @ElliottFrisch Yes. (Are you testing me? Sun [owned by Oracle] is currently developing Java, so the Java 8 `DateTimeFormatter` was created by _them_.) – Stefan S. Mar 09 '18 at 06:23
  • Sun didn't remove the German date format; they made the default parser less lenient. And, as you note, they don't exist anymore. So I would assume they didn't do this. – Elliott Frisch Mar 09 '18 at 06:25
  • @ElliottFrisch Have it your way. Removing the periods and only allowing slashes would also make the formatter "less lenient", and would also make it impossible to use the German date format most people use. But sure, it would still be okay, since de jure the default format is ISO. – Stefan S. Mar 09 '18 at 06:35
  • @SteffiS. [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) is the way to go. – Elliott Frisch Mar 09 '18 at 07:07
  • @ElliottFrisch I know, I know. It's just the Germans that are uncooperative. – Stefan S. Mar 09 '18 at 14:15

0 Answers0