DatePicker.setMinDate(long minDate) throws IllegalArgumentException: Time not between
The problem was that hours, minutes, seconds and milliseconds of the calendars that I was using for setting the DatePicker
's minDate
and maxDate
got set to the values correspondent to what time it was when Calendar.getInstance()
was called. And when I passed the day, month and year to the constructor of DatePickerDialog
, the dates were the same, but the milliseconds differed. So it could happen that the milliseconds set in maxDate were smaller than the milliseconds set in the DatePicker
's current time, therefore the date the DatePicker
was supposed to show was evaluated as bigger than maxDate
(even though it was still the same day, just with some more milliseconds)... And similarly for minDate
.
I hope it's understandable.
So what helped was to set the calendars to the last millisecond of the day when using them for setting maxDate
and to the first millisecond of the day when using them for setting minDate
. Like so:
(Just a piece of code from the else
clause.)
dpd.setTitle(getString(R.string.end_of_interval));
cal.add(Calendar.MONTH, 6);
cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
dpd.getDatePicker().setMaxDate(cal.getTimeInMillis());
cal.set(someTimeDuringYear1, someTimeDuringMonth1 - 1, someTimeDuringDay1);
cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));
cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
dpd.getDatePicker().setMinDate(cal.getTimeInMillis());
Hope it will be helpful to someone.
Also if someone comes up with a more elegant solution, please let me know.
I got the same exception when today is not in [minDate, maxDate]. But if I changed my code to call setMinDate()
before setMaxDate()
, it worked.
To enhance the above answer I decided to post this.
When calling setMaxDate() multiple times, let's say a dynamic change in onPrepareDialog(), you must make sure the new max year is not equal to the previous max year or the new max day is equal to the old max day.
Sounds strange but this is the source code from grep code
public void setMaxDate(long maxDate) {
mTempDate.setTimeInMillis(maxDate);
if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
&& mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
return;
}
mMaxDate.setTimeInMillis(maxDate);
mCalendarView.setMaxDate(maxDate);
if (mCurrentDate.after(mMaxDate)) {
mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
updateCalendarView();
}
updateSpinners();
}
So for me, I called setMaxDate() twice. Once with a dummy value where the years are offset by +100 and a second time for the actual fields I want.
Here is the combined result:
maxDate.set(Calendar.HOUR_OF_DAY, maxDate.getMaximum(Calendar.HOUR_OF_DAY));
maxDate.set(Calendar.MINUTE, maxDate.getMaximum(Calendar.MINUTE));
maxDate.set(Calendar.SECOND, maxDate.getMaximum(Calendar.SECOND));
maxDate.set(Calendar.MILLISECOND, maxDate.getMaximum(Calendar.MILLISECOND));
maxDateDummy.set(Calendar.HOUR_OF_DAY, maxDate.getMaximum(Calendar.HOUR_OF_DAY));
maxDateDummy.set(Calendar.MINUTE, maxDate.getMaximum(Calendar.MINUTE));
maxDateDummy.set(Calendar.SECOND, maxDate.getMaximum(Calendar.SECOND));
maxDateDummy.set(Calendar.MILLISECOND, maxDate.getMaximum(Calendar.MILLISECOND));
//update the dummy date by 100 years to force android OS to change max time.
maxDateDummy.set(Calendar.YEAR, maxDateDummy.get(Calendar.YEAR) + 100);
datePicker.setMaxDate(maxDateDummy.getTimeInMillis());
datePicker.setMaxDate(maxDate.getTimeInMillis());