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: Это первый вопрос, который я задал здесь, поэтому прошу прощения, если в этом что-то не так. Я буду рад предоставить любую недостающую информацию о том, что происходит.
РЕДАКТИРОВАТЬ: Как ни странно, хотя проблема возникает в строке, когда я пытаюсь установить minDate
, на самом деле кажется, что дата "больше", чем maxDate
, Причина, по которой я верю в это, состоит в том, что если я передаю someTimeDuringDay2 - 1
вместо someTimeDuringDay2
конструктору DatePickerDialog
, проблема исчезнет. Но тогда поле "день" в DatePicker
действительно на один меньше, чем я хочу. Мне нужно, чтобы он был установлен на someTimeDuringDay2
, когда отображается DatePickerDialog
, а не на someTimeDuringDay2 - 1
. Но у него, похоже, проблема, когда дата такая же, как и ее maxDate
.
Ответы
Ответ 1
Проблема заключалась в том, что часы, минуты, секунды и миллисекунды календарей, которые я использовал для установки DatePicker
minDate
и maxDate
, были установлены в значения, соответствующие времени, которое было, когда 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());
Надеюсь, что это будет полезно кому-то.
Также, если кто-то придумает более элегантное решение, сообщите мне.
Ответ 2
У меня такое же исключение, когда сегодня нет в [minDate, maxDate]. Но если я изменил свой код на вызов setMinDate()
до setMaxDate()
, он сработал.
Ответ 3
Чтобы усилить ответ выше, я решил опубликовать это.
При вызове 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(). Один раз с фиктивным значением, где годы смещены на +100 и второй раз для фактических полей, которые я хочу.
Вот объединенный результат:
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
Я получал ту же ошибку, я исправил ее, установив
dialog.getDatePicker().setCalendarViewShown(false);
в приложении любой был календарный запрос не требуется, вот что я сделал
Calendar tempDate =Calendar.getInstance();
dialog.getDatePicker().setMaxDate(Calendar.getInstance().getTimeInMillis();
dialog.getDatePicker().setCalendarViewShown(false);
tempDate.add(Calendar.YEAR, -120);
dialog.getDatePicker().setMinDate(tempDate.getTimeInMillis());
Ответ 5
Имел подобную проблему с 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());
Ответ 6
Это то, что я сделал для той же ошибки, что и на DatePicker. Таким образом, к тому времени, когда я устанавливал MaxDate и MinDate на DatePicker, миллисекунды менялись. Для моего приложения не имело значения, была ли эта дата на одну секунду. Мне нужно разницу между min и maxdates как два дня.
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);
Надеюсь, это поможет кому-то. Это приведет к тому, что установленная дата будет находиться между границами. Возможно, вам придется изменить смещение на основе вашего приложения.
Ответ 7
Я решил подобную проблему, установив лимит календаря на год (с сегодняшнего дня)
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());
Ответ 8
В моем случае я установил минимальную дату после установки максимальной даты. Это вызывает аварию.
До:
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);
}