1
\$\begingroup\$

We have a class which acts as a time interval, containing a LocalDate and two counts of minutes since midnight. One of the methods on this class converts these values into two DateTimes. Since DateTime has time zone information built-in this conversion might fail if the time is in the daylight savings time "gap", i.e. the hour which disappears when going from winter time to summer time. Instead I would like any such time to be advanced to the earliest later valid time, i.e. the time where the gap ends.

To solve this problem I have created the following method.

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

public class DstCorrector {
    public static DateTime getDateTimeCorrected(LocalDate localDate, int minutes) {
        DateTimeZone timeZone = DateTimeZone.getDefault();

        //Construct a LocalDateTime(which has no timezone)
        LocalDateTime startDateTime = localDate.toLocalDateTime(LocalTime.MIDNIGHT.plusMinutes(minutes));

        //Check if this time is in the DST gap, given the current time zone
        if(timeZone.isLocalDateTimeGap(startDateTime)) {
            //correct the time by moving it to the end of the gap
            long dayStartMillis = startDateTime.toLocalDate().toDateTimeAtStartOfDay().getMillis();
            long endOfGapMillis = timeZone.nextTransition(dayStartMillis);
            return new DateTime(endOfGapMillis, timeZone);
        }

        return localDate.toDateTime(LocalTime.MIDNIGHT.plusMinutes(minutes));
    }
}

With this test demonstrating expected behavior:

@Test
public void test() throws Exception {
    DateTime dateTimeCorrected = DstCorrector.getDateTimeCorrected(new LocalDate(2017, MARCH, 26), 150);//2:30 AM
    assertEquals(new DateTime(2017, MARCH, 26, 3, 0), dateTimeCorrected);
}

Is there a better way to do this? I dislike the snippet inside the if, specifically that I am unable to get the exact millis of the invalid time, using the start of the day instead. I know DateTimeZone has methods for converting to and from UTC which can be used to similar effect, but that converts by subtracting an hour from any time in the DST gap, which doesn't work in our case.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.