Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8304925

Some date/time strings created with JDK <=19 can not be parsed since JDK 20

    XMLWordPrintable

Details

    • b21
    • 20
    • generic
    • generic

    Description

      A DESCRIPTION OF THE PROBLEM :
      We just hit a blocker trying to switch to JDK 20 at work. Generated date format strings changed, and we can not parse some date strings with JDK 20 that were generated with JDK 19 (or earlier), because now a non-breaking space is used in some places that just had a regular space before:

      // using java.text.DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH)
      // or java.time.format.DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).localizedBy(Locale.ENGLISH)
      JDK 19: "3/23/23, 2:30 PM"
      JDK 20: "3/23/23, 2:30[NBSP]PM"

      As far as I can tell, this was a deliberate change: https://bugs.openjdk.org/browse/JDK-8284840

      But this will cause trouble for anyone that writes out and parses dates using the JDKs built in DateFormats or DateTimeFormatters. It's especially bad where users can edit date strings in a form, since they certainly won't put a non-breaking space before the AM/PM.
      We can't move to JDK 20 easily because of this; we need to analyse our entire code base and search for all DateFormat/DateTimeFormatter instances which might now use the non-breaking space, to replace them with explicit format strings for every locale we support.

      I would guess that we are not the only people in the world that try to parse user-editable date strings.

      REGRESSION : Last worked in version 19.0.2

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) use JDK 19 or earlier
      2) created a DateFormat instance via DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH);
         or a DateTimeFormatter instance via DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).localizedBy(Locale.ENGLISH))
      3) use that to generate a date/time string of the form: "3/23/23, 2:29 PM" (contains no NBSP)
      4) save that to a file "test.txt"
      5) switch to JDK 20 or later
      6) create a formatter instance like in step 2
      7) read the date string from the file created in step 4
      8) try to parse it with the formatter
      4) parse
      - create

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The string is parsed into a valid date
      ACTUAL -
      An Exception is thrown. Depending on which formatter class was used:

      java.text.DateFormat
      // Exception in thread "main" java.text.ParseException: Unparseable date: "3/23/23, 2:30 PM"
      // at java.base/java.text.DateFormat.parse(DateFormat.java:399)
      // at Scratch2.main(scratch_3.java:29)

      java.time.format.DateTimeFormatter
      // Exception in thread "main" java.time.format.DateTimeParseException: Text '3/23/23, 3:11 PM' could not be parsed at index 13
      // at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2106)
      // at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1934)
      // at Scratch2.main(scratch_3.java:32)

      ---------- BEGIN SOURCE ----------
      import java.io.BufferedReader;
      import java.io.BufferedWriter;
      import java.io.FileReader;
      import java.io.FileWriter;
      import java.text.DateFormat;
      import java.time.format.DateTimeFormatter;
      import java.time.format.FormatStyle;
      import java.util.Date;
      import java.util.Locale;

      // run with JDK 19
      class Scratch {
         public static void main(String[] args) throws Exception {
            try (var writer = new BufferedWriter(new FileWriter("test.txt"))) {
               var df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH);
               var dateString = df.format(new Date(1679578205994L));
               // var dateString = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).localizedBy(Locale.ENGLISH).format(LocalDateTime.now());
               writer.append(dateString); // writes: "3/23/23, 2:29 PM"
               writer.newLine();
            }
         }
      }

      // run with JDK 20
      class Scratch2 {
         public static void main(String[] args) throws Exception {
            try (var reader = new BufferedReader(new FileReader("test.txt"))) {
               var dateString = reader.readLine();
               var df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH);
               var date = df.parse(dateString); // BOOM
               // Exception in thread "main" java.text.ParseException: Unparseable date: "3/23/23, 2:30 PM"
               // at java.base/java.text.DateFormat.parse(DateFormat.java:399)
               // at Scratch2.main(scratch_3.java:29)
               
               // similar issue with DateTimeFormatter
               var date2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).localizedBy(Locale.ENGLISH).parse(dateString); // BOOM
               // Exception in thread "main" java.time.format.DateTimeParseException: Text '3/23/23, 3:11 PM' could not be parsed at index 13
               // at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2106)
               // at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1934)
               // at Scratch2.main(scratch_3.java:32)
            }
         }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I was in contact with someone and was relayed the following options

      1) take the time to adjust our code base to deal with NBSP in date formats
      2) Use the legacy locale data by designating -Djava.locale.providers=COMPAT at the launcher command line. (This option limits some newer functionalities though.)
      3) Ask Unicode CLDR to revert the format.

      I suspect option 3 has little to no chance of success though, since the change in Unicode CLDR has been in place for a bit now, and JDK isn't the only software that tries to adhere to it.

      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              naoto Naoto Sato
              webbuggrp Webbug Group
              Votes:
              1 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: