JDK-8211337 : ZonedDateTime.parse() not correctly handling MST zone (U.Mountain Standard Time)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.time
  • Affected Version: 11,12
  • Priority: P3
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: generic
  • CPU: generic
  • Submitted: 2018-09-24
  • Updated: 2018-10-09
  • Resolved: 2018-10-04
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Confirmed on Ubuntu x64 Linux and Windows 10.

A DESCRIPTION OF THE PROBLEM :
JDK 8's ZonedTimeTime.parse() correctly parses a date+time with MST correctly but with JDK 11 (and also JDK10.0.2) the value is incorrectly parsed.

REGRESSION : Last worked in version 8u181

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test case.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Correctly parsed value using Java 8:

  Original value: 2017-01-12T23:00MST
 Converted value: 2017-01-12T23:00-07:00[America/Denver]

ACTUAL -
Incorrectly result using Java 10 and 11ea:

  Original value: 2017-01-12T23:00MST
 Converted value: 2017-01-12T16:00-07:00[America/Denver]

---------- BEGIN SOURCE ----------
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;

public class ZonedDateTimeTestCase {

  // comprehensive pattern to handle any type of ISO8601 Date / Date-Time
  private static final String comprehensivePattern = "[yyyyMMdd][yyyy-MM-dd][yyyy-DDD]"
          + "['T'[HHmmss][HHmm][HH:mm:ss][HH:mm][.SSSSSSSSS]"
          + "[.SSSSSS][.SSS][.SS][.S]][OOOO][O][z][XXXXX][XXXX]['['VV']']";

  // formatter used to parse an ISO8601 string using the comprehensive pattern
  // pattern includes default values for time in case time information is missing
  private static final DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
          .append(DateTimeFormatter.ofPattern(comprehensivePattern))
          .parseDefaulting(ChronoField.OFFSET_SECONDS, ZoneOffset.UTC.getTotalSeconds())
          .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
          .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
          .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
          .toFormatter();

  private static final String testDate1 = "2017-01-12T23:00MST";

  public static final void main(String[] args) {
    final ZonedDateTime convertedValue = ZonedDateTime.parse(testDate1, dateFormatter);
    System.out.println("  Original value: " + testDate1);
    System.out.println(" Converted value: " + convertedValue.toString());
  }
}

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

CUSTOMER SUBMITTED WORKAROUND :
None that I'm aware of.

FREQUENCY : always



Comments
The issue here is mostly with a poor pattern. The OP is trying to use optional sections to get the effect of "choose one of these", when in fact the parser could match multiple of the optional sections. java.time.* does not support the kind of optional parsing the OP is seeking. Specifically on the offsets, this section "[OOOO][O][z]" could be simplified to "[z]" as zone parsing also accepts offsets. The clash the issue observes occurs because `.parseDefaulting(ChronoField.OFFSET_SECONDS, ZoneOffset.UTC.getTotalSeconds()) ` is specified. If that is removed, I suspect a different result would be seen. The behaviour of parsing probably could be changed such that `parseDefaulting(ChronoField.OFFSET_SECONDS ...)` is only applied if there is no time-zone parsed, but I think that would add extra complexity for an unusual edge case.
04-10-2018

ZonedDateTime.parse() has been changed to put priority on OFFSET over ZONE (JDK-8066982). Since the test case provides both (offset == 0 implying UTC, and America/Denver zone), offset takes the priority thus it s parsed in UTC zone, then converted to America/Denver (MST) zone.
04-10-2018

To reproduce the issue, run the attached test case. JDK 8u181 - Pass JDK 9 - Fail JDK 11+28 - Fail JDK 12-ea - Fail Output in JDK 11: Original value: 2017-01-12T23:00MST Converted value: 2017-01-12T16:00-07:00[America/Denver] Output in JDK 8u181 : Original value: 2017-01-12T23:00MST Converted value: 2017-01-12T23:00-07:00[America/Denver]
01-10-2018