Details
Description
ADDITIONAL SYSTEM INFORMATION :
Reproduced on OpenJDK Java 1.8.0_292 (Linux), 11.0.11(Linux) and 17.0.1 (Linux&Mac)
A DESCRIPTION OF THE PROBLEM :
Using the ZonedDateTime the parsing of a datetime String that does not include an offset (so no +01:00) but does include the 'z' = "daylight savings aware zone name" then parsing in the DST transition in the Fall fails to produce the correct result.
Assume this DateTimeFormatter that does not use an offset but does have the name of the timezone 'z'.
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
This 'z' is defined on https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/format/DateTimeFormatter.html as "If the pattern letter is 'z' the output is the daylight savings aware zone name."
So when formatting a time using this format under ZondeId "Europe/Amsterdam" you get either "CET" or "CEST".
The problem is that when parsing a String in this format with this specification the distinction between "CET" and "CEST" is lost.
Normally a round trip over "parse" and "format" results in the original input again.
I found this fails in the hour when the clock moves back to transition from summertime to wintertime.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
System.out.println(fmt.format(ZonedDateTime.parse("2021-10-31 02:30:00.000 CET", fmt)));
System.out.println(fmt.format(ZonedDateTime.parse("2021-10-31 02:30:00.000 CEST", fmt)));
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
2021-10-31 02:30:00.000 CET
2021-10-31 02:30:00.000 CEST
ACTUAL -
2021-10-31 02:30:00.000 CEST
2021-10-31 02:30:00.000 CEST
---------- BEGIN SOURCE ----------
App.java:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class App {
public static void main(String[] args) {
expectSame("2021-10-31 02:30:00.000 CET");
expectSame("2021-10-31 02:30:00.000 CEST");
expectSame("2021-11-07 01:30:00.000 EDT");
expectSame("2021-11-07 01:30:00.000 EST");
}
public static void expectSame(String datetimeString) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
String roundTrip = fmt.format(ZonedDateTime.parse(datetimeString, fmt));
System.out.println(
datetimeString + " | " +
roundTrip +
(datetimeString.equals(roundTrip) ? "" : " <--- BAD")
);
}
}
Then just do:
$ javac App.java && java App
2021-10-31 02:30:00.000 CET | 2021-10-31 02:30:00.000 CEST <--- BAD
2021-10-31 02:30:00.000 CEST | 2021-10-31 02:30:00.000 CEST
2021-11-07 01:30:00.000 EDT | 2021-11-07 01:30:00.000 EDT
2021-11-07 01:30:00.000 EST | 2021-11-07 01:30:00.000 EDT <--- BAD
---------- END SOURCE ----------
FREQUENCY : always
Reproduced on OpenJDK Java 1.8.0_292 (Linux), 11.0.11(Linux) and 17.0.1 (Linux&Mac)
A DESCRIPTION OF THE PROBLEM :
Using the ZonedDateTime the parsing of a datetime String that does not include an offset (so no +01:00) but does include the 'z' = "daylight savings aware zone name" then parsing in the DST transition in the Fall fails to produce the correct result.
Assume this DateTimeFormatter that does not use an offset but does have the name of the timezone 'z'.
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
This 'z' is defined on https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/format/DateTimeFormatter.html as "If the pattern letter is 'z' the output is the daylight savings aware zone name."
So when formatting a time using this format under ZondeId "Europe/Amsterdam" you get either "CET" or "CEST".
The problem is that when parsing a String in this format with this specification the distinction between "CET" and "CEST" is lost.
Normally a round trip over "parse" and "format" results in the original input again.
I found this fails in the hour when the clock moves back to transition from summertime to wintertime.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
System.out.println(fmt.format(ZonedDateTime.parse("2021-10-31 02:30:00.000 CET", fmt)));
System.out.println(fmt.format(ZonedDateTime.parse("2021-10-31 02:30:00.000 CEST", fmt)));
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
2021-10-31 02:30:00.000 CET
2021-10-31 02:30:00.000 CEST
ACTUAL -
2021-10-31 02:30:00.000 CEST
2021-10-31 02:30:00.000 CEST
---------- BEGIN SOURCE ----------
App.java:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class App {
public static void main(String[] args) {
expectSame("2021-10-31 02:30:00.000 CET");
expectSame("2021-10-31 02:30:00.000 CEST");
expectSame("2021-11-07 01:30:00.000 EDT");
expectSame("2021-11-07 01:30:00.000 EST");
}
public static void expectSame(String datetimeString) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS z");
String roundTrip = fmt.format(ZonedDateTime.parse(datetimeString, fmt));
System.out.println(
datetimeString + " | " +
roundTrip +
(datetimeString.equals(roundTrip) ? "" : " <--- BAD")
);
}
}
Then just do:
$ javac App.java && java App
2021-10-31 02:30:00.000 CET | 2021-10-31 02:30:00.000 CEST <--- BAD
2021-10-31 02:30:00.000 CEST | 2021-10-31 02:30:00.000 CEST
2021-11-07 01:30:00.000 EDT | 2021-11-07 01:30:00.000 EDT
2021-11-07 01:30:00.000 EST | 2021-11-07 01:30:00.000 EDT <--- BAD
---------- END SOURCE ----------
FREQUENCY : always
Attachments
Issue Links
- relates to
-
JDK-8177819 DateTimeFormatterBuilder zone parsing should recognise DST
- Resolved