javaandroiddatetimejodatimeandroid-jodatime

Jodatime IllegalInstantException


I've tried almost everything about this snippet, and I still get IllegalInstentException.

public int getDateDay() {
    DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
    DateTime dt;
    try {
        dt = formatter.parseDateTime(date);
    } catch (IllegalInstantException e) {
        dt = formatter.parseLocalDateTime(date).toDateTime();
    }
    return dt.getDayOfMonth();
}

Fatal Exception: org.joda.time.IllegalInstantException Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2018-10-21T00:00:00.000 (America/Sao_Paulo) keyboard_arrow_up arrow_right org.joda.time.chrono.ZonedChronology.localToUTC (ZonedChronology.java:157) org.joda.time.chrono.ZonedChronology.getDateTimeMillis (ZonedChronology.java:122) org.joda.time.chrono.AssembledChronology.getDateTimeMillis (AssembledChronology.java:133) org.joda.time.base.BaseDateTime. (BaseDateTime.java:257) org.joda.time.DateTime. (DateTime.java:532) org.joda.time.LocalDateTime.toDateTime (LocalDateTime.java:750) org.joda.time.LocalDateTime.toDateTime (LocalDateTime.java:731)


Solution

  • Seems the input is not a valid date. The problem has been discussed in this page.

    Reason:

    Joda-Time only allows the key classes to store valid date-times. For example, 31st February is not a valid date so it can't be stored (except in Partial).

    The same principle of valid date-times applies to daylight savings time (DST). In many places DST is used, where the local clock moves forward by an hour in spring and back by an hour in autumn/fall. This means that in spring, there is a "gap" where a local time does not exist.

    The error "Illegal instant due to time zone offset transition" refers to this gap. It means that your application tried to create a date-time inside the gap - a time that did not exist. Since Joda-Time objects must be valid, this is not allowed.

    Possible solutions may be as follows:

    • Use LocalDateTime, as all local date-times are valid.

    • When converting a LocalDate to a DateTime, then use toDateTimeAsStartOfDay() as this handles and manages any gaps.

    • When parsing, use parseLocalDateTime() if the string being parsed has no time-zone.