web-dev-qa-db-ja.com

DatePicker.setMinDate(long minDate)はIllegalArgumentExceptionをスローします:時間は間にありません

開始日と終了日で構成される時間間隔があります。 DatePickerDialogsを使用してユーザーにこれらの日付を設定させる方法があります。ダイアログを作成して表示するメソッドのコードは次のとおりです。

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));
}

beginning変数の値は、ユーザーが間隔の開始日または終了日を編集することを選択したかどうかを決定します。これらのsomeTimeDuringYear1などは開始日に関連するメンバー変数であり、someTimeDuringYear2などは間隔の終了日に関連しています。これらはすべて、このダイアログが作成されて表示される前に事前設定されています。

開始間隔と終了間隔の両方を編集しているときに例外がスローされます。間隔の終了日を編集することを選択したとしましょう。日付を許可されている最後の日付に設定するまで、すべてが完全に機能します。それを行って確認すると、すべて問題ないように見えますが、間隔の終了日を再度編集しようとすると、アプリケーションがクラッシュし、例外がスローされます。 (間隔の開始日を最後に許可された日付に設定してから、もう一度編集しようとすると、同じことが起こります。)

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)

私は答えを探していて、午後中ずっと解決策を考え出そうとしています。どんな助けでも大歓迎です。

ありがとうございました。

PS:これは私がここで尋ねる最初の質問なので、何か問題があればお詫びします。何が起こっているのかについて不足している情報を提供させていただきます。

EDIT:不思議なことに、minDateを設定しようとすると問題が発生しますが、実際には日付がmaxDate。これを信じる理由は、someTimeDuringDay2 - 1の代わりにsomeTimeDuringDay2DatePickerDialogのコンストラクターに渡すと、問題がなくなるためです。しかし、DatePickerの「日」フィールドは、実際には私が望むよりも1つ小さくなっています。 DatePickerDialogが表示されたら、someTimeDuringDay2ではなくsomeTimeDuringDay2 - 1に設定する必要があります。ただし、日付がmaxDateと同じ場合は、問題があるようです。

17
zbr

問題は、DatePickerminDatemaxDateを設定するために使用していたカレンダーの時間、分、秒、ミリ秒が、時刻に対応する値に設定されることでした。 Calendar.getInstance()が呼び出されたときでした。そして、日、月、年をDatePickerDialogのコンストラクターに渡したとき、日付は同じでしたが、ミリ秒が異なっていました。したがって、maxDateに設定されたミリ秒がDatePickerの現在の時刻に設定されたミリ秒よりも小さいため、DatePickerが表示するはずの日付がmaxDate(それでも同じ日でしたが、ミリ秒が少し増えました)...そしてminDateについても同様です。

理解できるといいのですが。

したがって、カレンダーをmaxDateの設定に使用する場合はその日の最後のミリ秒に設定し、minDateの設定に使用する場合はその日の最初のミリ秒に設定することが役立ちました。そのようです:

else句のコードの一部です。)

        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());

それが誰かに役立つことを願っています。

また、誰かがよりエレガントな解決策を思いついた場合は、私に知らせてください。

28
zbr

今日が[minDate、maxDate]にないときに、同じ例外が発生しました。しかし、setMinDate()の前にsetMaxDate()を呼び出すようにコードを変更すると、機能しました。

8
Wei Liu

上記の答えを強化するために、私はこれを投稿することにしました。

SetMaxDate()を複数回呼び出す場合、たとえばonPrepareDialog()の動的な変更の場合、新しい最大年が前の最大年と等しくないか、新しい最大日が古い最大日と等しいことを確認する必要があります。

奇妙に聞こえますが、これは 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();
}

だから私にとっては、setMaxDate()を2回呼び出しました。 1回目は年が+100オフセットされたダミー値で、2回目は必要な実際のフィールドです。

組み合わせた結果は次のとおりです。

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());  
4
LEO

同じエラーが発生しました。設定して修正します

dialog.getDatePicker().setCalendarViewShown(false); 

アプリではcalenderviewは必要ありませんでした、これは私がしたことです

Calendar tempDate =Calendar.getInstance(); 
dialog.getDatePicker().setMaxDate(Calendar.getInstance().getTimeInMillis();
dialog.getDatePicker().setCalendarViewShown(false);
tempDate.add(Calendar.YEAR, -120);
dialog.getDatePicker().setMinDate(tempDate.getTimeInMillis());
2
Faheem

SetMinDateで同様の問題がありましたが、これで解決しました。

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());
2
GOTuser2673068

これは、DatePickerで発生したのと同じエラーに対して行ったことです。したがって、DatePickerでMaxDateとMinDateを設定するまでに、ミリ秒は変化していました。私のアプリケーションでは、日付が1秒ずれているかどうかは問題ではありませんでした。 minとmaxdatesの差を2日にする必要がありました。

        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getDefault());
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);

        DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(), this, year, month, day);
        long OFFSET = 1000 ; //milli seconds offset for your date.
        datePickerDialog.getDatePicker().setMaxDate(c.getTimeInMillis() + 1 * OFFSET);
        c.add(Calendar.DAY_OF_MONTH, -1);
        datePickerDialog.getDatePicker().setMinDate(c.getTimeInMillis() - 1 * OFFSET);

これが誰かを助けることを願っています。これにより、日付が範囲内に設定されたままになります。アプリケーションに基づいてオフセットを変更する必要がある場合があります。

1
Maddy

私の場合、最大日付を設定した後に最小日付を設定します。クラッシュの原因になります。

前 :

_if (!currentDateandTimeSampai.equalsIgnoreCase("")) {
    datePickerDialog.getDatePicker().setMaxDate(end.getTime());
} 
_

datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);

後:

datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);

_if (!currentDateandTimeSampai.equalsIgnoreCase("")) {
     if (isSameDate(new Date(), end)){
          datePickerDialog.getDatePicker().setMaxDate(new Date().getTime());
     }else {
          datePickerDialog.getDatePicker().setMaxDate(end.getTime());
     }
 }
_

この関数を追加して、maxDateが現在の日と同じ日であることを確認できます。

_public boolean isSameDate(Date date1, Date date2) {
    Calendar cal1 = Calendar.getInstance();
    Calendar cal2 = Calendar.getInstance();
    cal1.setTime(date1);
    cal2.setTime(date2);
    return cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
            cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
}
_
0
Rembulan Moon

カレンダーの制限を1年(今日の日付から)に設定することで、同様の問題を解決しました

    long A_YEAR_MILLISECOND = 12 * 30 * 24 * 60 * 60 * 1000L;

    datePickerDialog.getDatePicker().setMaxDate(Calendar.getInstance().getTimeInMillis() + A_YEAR_MILLISECOND);
    datePickerDialog.getDatePicker().setMinDate(Calendar.getInstance().getTimeInMillis());
0
Shayan_Aryan