Reputation: 914
I am using Java 17. I am trying to parse different strings as ZonedDateTime but when I try to convert it to an Instant, the output is not as expected. For eg:
String first = "2020-01-08T21:00:00Z[Europe/Berlin]";
ZonedDateTime zone1 = ZonedDateTime.parse(first);
String second = "2020-01-08T20:00:00Z[UTC]";
ZonedDateTime zone2 = ZonedDateTime.parse(second);
System.out.println(zone1.toInstant());
System.out.println(zone2.toInstant());
The output is (this is wrong, both times should be same):
2020-01-08T21:00:00Z
2020-01-08T20:00:00Z
However, when I create a ZonedDateTime object using constructor and ZoneId I get correct output:
ZonedDateTime z1 = ZonedDateTime.of(2020,1,8,21,0,0,0,ZoneId.of("Europe/Berlin"));
System.out.println(z1.toInstant());
ZonedDateTime z2 = ZonedDateTime.of(2020,1,8,20,0,0,0,ZoneId.of("UTC"));
System.out.println(z2.toInstant());
Output:
2020-01-08T20:00:00Z
2020-01-08T20:00:00Z
Can anyone tell me why my parse method is not working as expected?
Note: This issue is NOT related to DST bug for ZonedTimeZone in JDK8:
Upvotes: 0
Views: 291
Reputation: 4809
You need to parse it and provide the correct format. Below code works for me.
var dateUtcPlus1 = "2025-01-10T17:15:00+01:00"
ZonedDateTime date1 = ZonedDateTime.parse(dateUtcPlus1, DateTimeFormatter.ISO_OFFSET_DATE_TIME).truncatedTo(ChronoUnit.SECONDS);
In fact I have a parameterized unit test to explain the same.
@ParameterizedTest(name = "Date {0} is {2} Date {1}")
@CsvSource({
"2025-01-10T17:15:00+01:00,2025-01-10T16:15:00+00:00,EqualTo",
"2025-01-10T15:15:00+05:00,2025-01-10T10:15:00+00:00,EqualTo",
"2025-01-10T12:15:00+05:00,2025-01-10T08:15:00+00:00,Before",
"2025-01-10T15:55:00+05:00,2025-01-10T10:45:00+00:00,After",
})
void testEqualTimesInDifferentZonesFromStringFormat(String sourceDate, String targetDate, String expectedResult) {
ZonedDateTime date1 = ZonedDateTime.parse(sourceDate, DateTimeFormatter.ISO_OFFSET_DATE_TIME).truncatedTo(ChronoUnit.SECONDS);
ZonedDateTime date2 = ZonedDateTime.parse(targetDate, DateTimeFormatter.ISO_OFFSET_DATE_TIME).truncatedTo(ChronoUnit.SECONDS);
if ("EqualTo".equals(expectedResult)) {
assertThat(date1).isEqualTo(date2);
} else if ("Before".equals(expectedResult)) {
assertThat(date1.isBefore(date2)).isTrue();
} else if ("After".equals(expectedResult)) {
assertThat(date1.isAfter(date2)).isTrue();
}
}
Upvotes: 0
Reputation: 7808
In your input string "2020-01-08T21:00:00Z[Europe/Berlin]"
(and the second one) remove 'Z' as that means that it is a UTC time and subsequent timezone is ignored. So, both of your times are in UTC meaning that the first one is NOT in [Europe/Berlin]
time zone. You might want to parse the strings using format mask using DateTimeFormatter
class. Or replace 'Z' with '+01:00' and then you don't need to use formatting.
Upvotes: 3