2

Same code of date parsing show different results depending if I am using Java 8 or Java 11.

Here are a code sample to reproduce the problem :

    public static void main(String[] args) {

    DateTimeFormatterBuilder dfBuilder = new DateTimeFormatterBuilder()
            .appendPattern("uuuu-M-d")
            .optionalStart()
            .optionalStart().appendLiteral(' ').optionalEnd()
            .optionalStart().appendLiteral('T').optionalEnd()
            .appendValue(ChronoField.HOUR_OF_DAY)
            .optionalStart()
            .appendLiteral(':')
            .appendValue(ChronoField.MINUTE_OF_HOUR)
            .optionalStart()
            .appendLiteral(':')
            .appendValue(ChronoField.SECOND_OF_MINUTE)
            .optionalStart()
            .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true)
            .optionalEnd()
            .optionalEnd()
            .optionalEnd()
            .appendPattern("[XXXXX][XXXX][XXX][XX][X]")
            .optionalEnd();
    DateTimeFormatter df = dfBuilder.toFormatter(Locale.FRANCE).withZone(ZoneId.of("Europe/Paris"));

    TemporalAccessor temporalAccessor = df.parse("1970-01-01T00:00:00.00Z");
    Instant instantTime = Instant.from(temporalAccessor);
    long epochTimestamp = instantTime.getEpochSecond();
    System.out.println(epochTimestamp);
}

On java 8 the output is -3600.

While on Java 11 the output is 0 (which is the value I am expecting).

From my analysis the origin is the use of "withZone()" method, if I remove it, it works as expected for dates that contains zone data.

But at the same this behavior is not the same on all DateTimeFormatter : for example if I use this formatter :

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM-dd HH:mm:ss")
                .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
                .optionalStart()
                .appendZoneId()
                .optionalEnd()
                .toFormatter()
                .withZone(ZoneId.of("Europe/Paris"));

The zoneId is well taken into account in case present inside the date (despite the fact "withZone() is called). So I suppose there is something wrong with the first formatter and that a default behavior on Java 11 helps it to work as expected on Java 11 but not on Java 8 ? Also I precise that my goal is to have it works on Java 8.

bloub
  • 510
  • 1
  • 4
  • 21
  • 1
    Please look at this https://stackoverflow.com/questions/58010818/dateformat-parse-of-dates-changed-behaviour-from-java-8-to-java-9-are-there-any I believe its the same issue. – Codeburned Oct 06 '21 at 11:22
  • 1
    @Codeburned Are you sure this is a localisation issue? The expected output is not related to the time in France. It is expected that the date time formatter parses the timezone from the character `Z` in the string, rather than from the argument passed to `withZone`. What have seemed to happened is that the formatter uses the timezone in `withZone` rather than the zone in the text. – Sweeper Oct 06 '21 at 11:28
  • 1
    @Codeburned It does not seems to be the exact same problem to me but maybe I am miss understanding something. Also the workaround seems not applicable to my case – bloub Oct 06 '21 at 11:45
  • 1
    I have reproduced the incorrect result on my Java 8. – Ole V.V. Oct 06 '21 at 12:16

1 Answers1

2

Known bug

It’s a known bug in Java 8. Parsing with DateTimeFormatter.withZone does not behave as described in javadocs.

Funnily the bug report in the Java Bugs System that I link to does not mention a fix version. It does mention that the bug is not in JDK 9-ea, though:

To reproduce the issue, run the attached test case. It fails on JDK 8u121 but passes in JDK 9-ea.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161