-
Bug
-
Resolution: Fixed
-
P4
-
16, 17
-
b13
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8273530 | 17.0.2 | Chris Hegarty | P4 | Resolved | Fixed | b01 |
JDK-8275122 | 11.0.15-oracle | Ravi Reddy | P4 | Resolved | Fixed | b01 |
JDK-8278487 | 11.0.15 | Goetz Lindenmaier | P4 | Resolved | Fixed | b01 |
JDK-8275127 | 8u331 | Ravi Reddy | P4 | Resolved | Fixed | b01 |
java 16.0.2 2021-07-20
Java(TM) SE Runtime Environment (build 16.0.2+7-67)
Java HotSpot(TM) 64-Bit Server VM (build 16.0.2+7-67, mixed mode, sharing)
I had a few older versions of java installed as well, and the same thing happened on Java 11 and Java 8
A DESCRIPTION OF THE PROBLEM :
If you build a DateTimeFormatter that accepts INSTANT_SECONDS only, and give it a time zone that experiences daylight savings transitions (I used America/New_York in my reproduction case, but saw it fail on some others), then use that formatter to parse an epoch date string, the resulting date is an hour earlier than it should be. This happens when transitioning from daylight savings time to standard time. Parsing the same timestamp with a different format got the correct result.
I did some tracing, and it looked to me like the problem happens in java.time.format.Parsed#resolve(), which seemed to convert the unambiguous INSTANT_SECONDS value into an ambiguous date + time + timezone value, then generated a fresh INSTANT_SECONDS value, and incorrectly chose the earlier of the two possible values.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Construct a DateTimeFormatter that read INSTANT_SECONDS in a time zone with daylight saving time. Try to parse a daylight savings time transition moment with that formatter. Observe the resulting INSTANT_SECONDS is not the value we read in.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
parsing epoch seconds should get the correct value
ACTUAL -
The parsed value was an hour earlier than expected.
---------- BEGIN SOURCE ----------
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.util.Locale;
public class DateParseBug {
public static void main(String[] args) {
final DateTimeFormatter epochSecondFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.INSTANT_SECONDS, 1, 19, SignStyle.NORMAL)
.toFormatter(Locale.ROOT)
.withZone(ZoneId.of("America/New_York"));
// This is the transition point from DST to Standard time for that year in America/New_York tz
ZonedDateTime sixAm = ZonedDateTime.of(2020, 11, 1, 6, 0, 0, 0, ZoneOffset.UTC);
TemporalAccessor actual = epochSecondFormatter.parse(epochSecondFormatter.format(sixAm));
if (actual.getLong(ChronoField.INSTANT_SECONDS) != sixAm.getLong(ChronoField.INSTANT_SECONDS)) {
System.out.println("Parsed back a wrong value. Expected: [" + sixAm.getLong(ChronoField.INSTANT_SECONDS) +
"] Actual: [" + actual.getLong(ChronoField.INSTANT_SECONDS) + "]");
} else {
System.out.println("Parsed Correctly");
}
}
}
---------- END SOURCE ----------
FREQUENCY : always
- backported by
-
JDK-8273530 Parsing epoch seconds at a DST transition with a non-UTC parser is wrong
- Resolved
-
JDK-8275122 Parsing epoch seconds at a DST transition with a non-UTC parser is wrong
- Resolved
-
JDK-8275127 Parsing epoch seconds at a DST transition with a non-UTC parser is wrong
- Resolved
-
JDK-8278487 Parsing epoch seconds at a DST transition with a non-UTC parser is wrong
- Resolved
- links to
-
Commit openjdk/jdk11u-dev/eaa4197f
-
Commit openjdk/jdk17u/0ced2aa7
-
Commit openjdk/jdk/fe7d7088
-
Review openjdk/jdk11u-dev/688
-
Review openjdk/jdk17u/54
-
Review openjdk/jdk/5225