I'm trying to parse a date from a String.
I'd like to identify the case where due to daylight savings, the clocks go back and a time is effectively "repeated" in the same day.
For example, based on UK daylight savings time, the clocks go back an hour at 2AM, 27/10/2019.
Therefore:
Therefore "1:30AM 27/10/2019" is referring to two different times. This is the case I am trying to identify.
I have created the following, but it uses Date
& Calendar
classes, and some deprecated methods. I'd like to do this using the new java.time
functionality - and I'm hoping there's an easier solution.
public static boolean isDateRepeatedDST(final Date date, TimeZone timeZone) {
if (timeZone == null) {
// If not specified, use system default
timeZone = TimeZone.getDefault();
}
if (timeZone.useDaylightTime()) {
// Initially, add the DST offset to supplied date
// Handling the case where this is the first occurrence
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MILLISECOND, timeZone.getDSTSavings());
// And determine if they are now logically equivalent
if (date.toLocaleString().equals(calendar.getTime().toLocaleString())) {
return true;
} else {
// Then try subtracting the DST offset
// Handling the second occurrence
calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MILLISECOND, -timeZone.getDSTSavings());
if (date.toLocaleString().equals(calendar.getTime().toLocaleString())) {
return true;
}
}
}
// Otherwise
return false;
}
ZoneId zone = ZoneId.of("Europe/London");
ZonedDateTime dateTime = ZonedDateTime.of(2019, 10, 27, 0, 30, 0, 0, zone);
for (int i = 0; i < 4; i++) {
System.out.println(dateTime);
dateTime = dateTime.plusHours(1);
}
Output:
2019-10-27T00:30+01:00[Europe/London] 2019-10-27T01:30+01:00[Europe/London] 2019-10-27T01:30Z[Europe/London] 2019-10-27T02:30Z[Europe/London]
You can see that the time 01:30 is repeated and that the offset is different the two times it comes.
If you want a test for whether a time is repeated:
public static boolean isDateRepeatedDST(ZonedDateTime dateTime) {
return ! dateTime.withEarlierOffsetAtOverlap().equals(dateTime.withLaterOffsetAtOverlap());
}
We can use it in the loop above if we modify the print statement:
System.out.format("%-37s %s%n", dateTime, isDateRepeatedDST(dateTime));
2019-10-27T00:30+01:00[Europe/London] false 2019-10-27T01:30+01:00[Europe/London] true 2019-10-27T01:30Z[Europe/London] true 2019-10-27T02:30Z[Europe/London] false