DatePicker.setMinDate(long minDate) throws IllegalArgumentException: Time not between

16,916

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());
Share:
16,916

Related videos on Youtube

zbr
Author by

zbr

www.linkedin.com/in/zabranskyr

Updated on September 15, 2022

Comments

  • zbr
    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. Those someTimeDuringYear1 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 the maxDate. The reason that I have for believing this is that if I pass someTimeDuringDay2 - 1 instead of someTimeDuringDay2 to the DatePickerDialog's constructor, the problem is gone. But then "day" field in the DatePicker is really by one smaller than I want it to be. I need it to be set to someTimeDuringDay2 when the DatePickerDialog is shown, not to someTimeDuringDay2 - 1. But it seems to have a problem when the date is the same as its maxDate.

  • sud007
    sud007 about 8 years
    I 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!