1

The date picker I used for my activity crashed on KitKat but works on every other newer operating systems. This is the exception I get on old devices:

java.lang.IllegalArgumentException: fromDate: Mon Apr 10 07:59:25 EDT 2017 does not precede toDate: Mon Apr 10 07:59:25 EDT 2017

Code block stack trace is pointing at:

private void showDatePicker(){
   DatePickerDialog datePickerDialog = new DatePickerDialog(
   getActivity(), this, calendar.get(Calendar.YEAR),  calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
   //this is where the crash happens
   datePickerDialog.getDatePicker().setMinDate(new Date().getTime());
   datePickerDialog.show();
}

Please let me know if the information regarding the question is sufficient. Any fix for this?

Jay
  • 4,873
  • 7
  • 72
  • 137
  • Possible duplicate of [How to set minimum DatePicker date to current date](http://stackoverflow.com/questions/13661788/how-to-set-minimum-datepicker-date-to-current-date) – Dhaval Patel Apr 10 '17 at 12:31

2 Answers2

2

I fix this issue applying a delay:

private void showDatePicker(){
   DatePickerDialog datePickerDialog = new DatePickerDialog(
   getActivity(), this, calendar.get(Calendar.YEAR),  calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
   //this is where the crash happens
   datePickerDialog.getDatePicker().setMinDate(new Date().getTime() - 10000);
   datePickerDialog.show();

}

Luiz Fernando Salvaterra
  • 4,192
  • 2
  • 24
  • 42
  • Any reason why it's happening? Also will this affect the behaviour on newer devices/OSs? – Jay Apr 10 '17 at 12:12
  • 1
    In my app this fix did not affect on the new devices/OS`s. I think this happens because the Android cannot set a min date that is the same as the current date. – Luiz Fernando Salvaterra Apr 10 '17 at 12:15
  • @Dinuka it happens due to a bug in CalendarView for pre-API21, and for calendarViewMode == MODE_HOLO for API21. For newer versions of SDK the code of CalendarView is different and doesn't contain the issue – std.denis Mar 01 '19 at 21:38
0

To solve this issue create a timestamp for minDate just before instantiation of DatePickerDialog:

private void showDatePicker(){
   long now = System.currentTimeMillis();
   DatePickerDialog datePickerDialog = new DatePickerDialog(
      getActivity(), this, calendar.get(Calendar.YEAR),  calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
   datePickerDialog.getDatePicker().setMinDate(now);
   datePickerDialog.show();
}

This crash happens due to a bug in CalendarView for pre-API21, and for calendarViewMode == MODE_HOLO for API21.

Although setMinDate contains a correction highlighted with a comment:

public void setMinDate(long minDate) {
    ...
    mMinDate.setTimeInMillis(minDate);
    // make sure the current date is not earlier than
    // the new min date since the latter is used for
    // calculating the indices in the adapter thus
    // avoiding out of bounds error
    Calendar date = mAdapter.mSelectedDate;
    if (date.before(mMinDate)) {
        mAdapter.setSelectedDay(mMinDate);
    }
    // reinitialize the adapter since its range depends on min date
    mAdapter.init();

The check in setSelectedDay compares mMinDate and mSelectedDate only with date accuracy:

public void setSelectedDay(Calendar selectedDay) {
    if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDate.get(Calendar.DAY_OF_YEAR)
            && selectedDay.get(Calendar.YEAR) == mSelectedDate.get(Calendar.YEAR)) {
        return;
    }

mSelectedDate and mMinDate are points into the same day, so that mSelectedDate will remain unchanged (i.e. in a wrong state mSelectedDate < mMinDate).

Then the control flow will run up to mAdapter.init, and then into getWeeksSinceMinDate. In this function a comparison of mMinDate and mSelectedDate will be performed with millisecond accuracy:

private int getWeeksSinceMinDate(Calendar date) {
    if (date.before(mMinDate)) {
        throw new IllegalArgumentException("fromDate: " + mMinDate.getTime()
                + " does not precede toDate: " + date.getTime());
    }

And because mSelectedDate was initialized in few milliseconds before mMinDate the crash will occur.

In a newer implementation this code was rewritten, so this issue is missing for API21+.

std.denis
  • 317
  • 3
  • 10