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

Fatal parse errors: shortname for September has been changed in Locale.UK.

XMLWordPrintable

    • 16
    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      With Java 1.8.0_292 and Java 11.0.11 on Linux this all works fine.
      With Java 17 it fails.

      A DESCRIPTION OF THE PROBLEM :
      In Java 8 and 11 formatting and parsing a date using the Locale.UK used the shortname "Sep" for September.
      With Java 17 this has changed to "Sept".
      Only September has been changed to 4 letters, all other months remain at the expected 3 letters.

      This change causes fatal parsing errors when trying to parse historical logging.

      Changing to a different Locale like Locale.US or Locale.ENGLISH is not an option as these do not follow the ISO standard about weekdays (i.e. the Monday/Sunday thing) which are fields I'm looking for in my code.
      I have not been able to find a locale that is "ENGLISH" and conforms to the ISO standards. Both Locale.US and Locale.ENGLISH do it the US way.

      Background: The tests in my project failed when trying to build it with Java 17
      https://github.com/nielsbasjes/logparser/blob/master/httpdlog/httpdlog-parser/src/test/java/nl/basjes/parse/httpdlog/dissectors/TestTimeStampDissector.java#L158


      REGRESSION : Last worked in version 11.0.14

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create a file September.java with the content below and then using Java 17 simply do: javac September.java && java September.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Specific lines from the output of the provided reproduction code:

      en_GB 01/Sep/2021:12:11:12 +0200
      en_GB Test case: 30/sep/2016:00:00:06 +0000 : Passed: {InstantSeconds=1475193606, OffsetSeconds=0},ISO,Europe/Amsterdam resolved to 2016-09-30T00:00:06


      ACTUAL -
      Specific lines from the output of the provided reproduction code:

      en_GB 01/Sept/2021:12:11:12 +0200
      en_GB Test case: 30/sep/2016:00:00:06 +0000 : Failed: Text '30/sep/2016:00:00:06 +0000' could not be parsed at index 3


      ---------- BEGIN SOURCE ----------
      import java.time.Instant;
      import java.time.ZoneId;
      import java.time.format.DateTimeFormatter;
      import java.time.format.DateTimeFormatterBuilder;
      import java.time.temporal.WeekFields;
      import java.util.Arrays;
      import java.util.List;
      import java.util.Locale;

      public class September {
          public static void main( String[] args ) {
              show(Locale.UK); // The default Locale that follows the ISO-8601 WeekFields
              show(Locale.US);
              show(Locale.ENGLISH);
          }

          public static void show(Locale locale) {
              System.err.println("===============: With Locale " + locale.toString());
              showWeekfields(locale);

              // The default parser to what we find in the Apache httpd Logfiles
              // [05/Sep/2010:11:27:50 +0200]
              String defaultApacheDateTimePattern = "dd/MMM/yyyy:HH:mm:ss ZZ";

              DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                  .parseCaseInsensitive()
                  .appendPattern(defaultApacheDateTimePattern)
                  .toFormatter()
                  .withLocale(locale)
                  .withZone(ZoneId.of("Europe/Amsterdam"));

              List<String> printCases = Arrays.asList(
                  "2021-01-01T10:11:12.00Z",
                  "2021-02-01T10:11:12.00Z",
                  "2021-03-01T10:11:12.00Z",
                  "2021-04-01T10:11:12.00Z",
                  "2021-05-01T10:11:12.00Z",
                  "2021-06-01T10:11:12.00Z",
                  "2021-07-01T10:11:12.00Z",
                  "2021-08-01T10:11:12.00Z",
                  "2021-09-01T10:11:12.00Z",
                  "2021-10-01T10:11:12.00Z",
                  "2021-11-01T10:11:12.00Z",
                  "2021-12-01T10:11:12.00Z");

              for (String testCase: printCases) {
                  System.err.println(locale.toString() + " " + formatter.format(Instant.parse(testCase)));
              }

              String timestamp = "30/sep/2016:00:00:06 +0000";
              System.err.print(locale + " Test case: " + timestamp + " : ");
              try {
                  System.err.println("Passed: " + formatter.parse(timestamp));
              } catch (Exception e) {
                  System.err.println("Failed: " + e.getMessage());
              }
          }

          public static void showWeekfields(Locale locale) {
              WeekFields localeWeekFields = WeekFields.of(locale);
              WeekFields isoWeekFields = WeekFields.ISO;
              if (localeWeekFields.getFirstDayOfWeek().equals(isoWeekFields.getFirstDayOfWeek())) {
                  System.err.println(locale + " has ISO FirstDayOfWeek");
              } else {
                  System.err.println(locale + " DOES NOT HAVE ISO FirstDayOfWeek");
              }
              if (localeWeekFields.getMinimalDaysInFirstWeek() == isoWeekFields.getMinimalDaysInFirstWeek()) {
                  System.err.println(locale + " has ISO MinimalDaysInFirstWeek");
              } else {
                  System.err.println(locale + " DOES NOT HAVE ISO MinimalDaysInFirstWeek");
              }
          }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The hack that seems to work in some specific cases is to catch the exception and using a regular expression replace "sep" with "sept" and then try again.


      FREQUENCY : always


            naoto Naoto Sato
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: