DatePicker.setMinDate(long minDate) throws IllegalArgumentException: Time not between
Solution 1
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.
Solution 2
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.
Solution 3
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());
Solution 4
I was getting the same error , I fix it by setting
dialog.getDatePicker().setCalendarViewShown(false);
in the app any was calenderview not required, This is what I did
Calendar tempDate =Calendar.getInstance();
dialog.getDatePicker().setMaxDate(Calendar.getInstance().getTimeInMillis();
dialog.getDatePicker().setCalendarViewShown(false);
tempDate.add(Calendar.YEAR, -120);
dialog.getDatePicker().setMinDate(tempDate.getTimeInMillis());
Solution 5
Had similar problem with setMinDate, this solved it:
int year=2017, month=1, day=1; // for min. date: 1. feb. 2017
Calendar cal = Calendar.getInstance();
cal.set( year, month, day, 0, 0, 0 ); //hour=0 min=0 sec=0
datePickerDialog.getDatePicker().setMinDate(cal.getTimeInMillis());
Related videos on Youtube
Comments
-
zbr over 1 year
I have a time interval consisting of a beginning and an end date. I have a way of letting the user set these dates through DatePickerDialogs. Here is the code of the method that creates and shows the dialogs:
private void editInterval(boolean beginning) { DatePickerDialog dpd; Calendar cal = Calendar.getInstance(); if (beginning) { dpd = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { someTimeDuringYear1 = year; someTimeDuringMonth1 = monthOfYear + 1; someTimeDuringDay1 = dayOfMonth; Calendar cal1 = Calendar.getInstance(); cal1.set(Calendar.YEAR, year); cal1.set(Calendar.MONTH, monthOfYear); cal1.set(Calendar.DAY_OF_MONTH, dayOfMonth); Calendar cal2 = Calendar.getInstance(); cal2.set(Calendar.YEAR, someTimeDuringYear2); cal2.set(Calendar.MONTH, someTimeDuringMonth2); cal2.set(Calendar.DAY_OF_MONTH, someTimeDuringDay2); if (cal1.getTimeInMillis() > cal2.getTimeInMillis()) { someTimeDuringYear2 = someTimeDuringYear1; someTimeDuringMonth2 = someTimeDuringMonth1; someTimeDuringDay2 = someTimeDuringDay1; } updateSomeTimeDuring(); editDepartureInterval(); } }, someTimeDuringYear1, someTimeDuringMonth1 - 1, someTimeDuringDay1); dpd.setTitle(getString(R.string.beginning_of_interval)); cal.add(Calendar.MONTH, 6); dpd.getDatePicker().setMaxDate(cal.getTimeInMillis()); cal.add(Calendar.MONTH, -6); cal.add(Calendar.DATE, 2); dpd.getDatePicker().setMinDate(cal.getTimeInMillis()); } else { dpd = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { someTimeDuringYear2 = year; someTimeDuringMonth2 = monthOfYear + 1; someTimeDuringDay2 = dayOfMonth; updateSomeTimeDuring(); editDepartureInterval(); } }, someTimeDuringYear2, someTimeDuringMonth2 - 1, someTimeDuringDay2); dpd.setTitle(getString(R.string.end_of_interval)); cal.add(Calendar.MONTH, 6); dpd.getDatePicker().setMaxDate(cal.getTimeInMillis()); cal.set(someTimeDuringYear1, someTimeDuringMonth1 - 1, someTimeDuringDay1); dpd.getDatePicker().setMinDate(cal.getTimeInMillis()); } dpd.show(); dpd.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); }
The value of the
beginning
variable determines whether the user has chosen to edit the beginning or end date of the interval. ThosesomeTimeDuringYear1
and similar are member variables related to the beginning date,someTimeDuringYear2
and similar are related to the end date of the interval. All of them are pre-set before this dialog is ever created and shown.The exception is thrown while editing both the beginning and the end interval. Let's say I choose to edit the interval's end date. Everything works perfectly until I set the date to the last date that I am allowed to. If I do that and confirm, everything still seems fine, but when I try to edit the interval's end date again, the application crashes and the exception is thrown. (The same thing happens if I set the interval's beginning date to the last allowed date and then try to edit it again.)
Here is the log from LogCat:
03-28 17:18:16.901: E/AndroidRuntime(6112): FATAL EXCEPTION: main 03-28 17:18:16.901: E/AndroidRuntime(6112): java.lang.IllegalArgumentException: Time not between Sat Mar 30 17:18:16 CET 2013 and Sat Sep 28 17:18:16 CEST 2013 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.widget.CalendarView.goTo(CalendarView.java:805) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.widget.CalendarView.setMinDate(CalendarView.java:487) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.widget.DatePicker.setMinDate(DatePicker.java:315) 03-28 17:18:16.901: E/AndroidRuntime(6112): at com.skypicker.android.MainActivity.editInterval(MainActivity.java:344) 03-28 17:18:16.901: E/AndroidRuntime(6112): at com.skypicker.android.MainActivity.access$10(MainActivity.java:296) 03-28 17:18:16.901: E/AndroidRuntime(6112): at com.skypicker.android.MainActivity$5.onClick(MainActivity.java:261) 03-28 17:18:16.901: E/AndroidRuntime(6112): at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:924) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.widget.AdapterView.performItemClick(AdapterView.java:292) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.widget.AbsListView.performItemClick(AbsListView.java:1063) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2519) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.widget.AbsListView$1.run(AbsListView.java:3173) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.os.Handler.handleCallback(Handler.java:605) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.os.Handler.dispatchMessage(Handler.java:92) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.os.Looper.loop(Looper.java:137) 03-28 17:18:16.901: E/AndroidRuntime(6112): at android.app.ActivityThread.main(ActivityThread.java:4424) 03-28 17:18:16.901: E/AndroidRuntime(6112): at java.lang.reflect.Method.invokeNative(Native Method) 03-28 17:18:16.901: E/AndroidRuntime(6112): at java.lang.reflect.Method.invoke(Method.java:511) 03-28 17:18:16.901: E/AndroidRuntime(6112): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787) 03-28 17:18:16.901: E/AndroidRuntime(6112): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554) 03-28 17:18:16.901: E/AndroidRuntime(6112): at dalvik.system.NativeStart.main(Native Method)
I have been looking for answers and trying to come up with a solution all afternoon. Any help is appreciated.
Thank you.
PS: This is the first question I ever ask here, so I apologize if there is something wrong about it. I'll be happy to provide any missing information about what's happening.
EDIT: Strangely enough, even though the problem raises on the line when I try to set the
minDate
, it actually seems to be that the date is "bigger" than themaxDate
. The reason that I have for believing this is that if I passsomeTimeDuringDay2 - 1
instead ofsomeTimeDuringDay2
to theDatePickerDialog
's constructor, the problem is gone. But then "day" field in theDatePicker
is really by one smaller than I want it to be. I need it to be set tosomeTimeDuringDay2
when theDatePickerDialog
is shown, not tosomeTimeDuringDay2 - 1
. But it seems to have a problem when the date is the same as itsmaxDate
. -
sud007 about 8 yearsI don't know what's the logic behind. That worked for me Totally! The catch is: This issue is only on jelly bean devices Lollipop devices are handling this. No idea about other android versions!