我有一个由开始日期和结束日期组成的时间间隔。我有办法让用户通过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
时问题就出现了问题,但实际上似乎日期比{更大'更大{1}}。我相信这一点的原因是,如果我将maxDate
而不是someTimeDuringDay2 - 1
传递给someTimeDuringDay2
的构造函数,问题就消失了。但是DatePickerDialog
中的“day”字段实际上比我想要的要小一些。我需要在显示DatePicker
时将其设置为someTimeDuringDay2
,而不是DatePickerDialog
。但是当日期与someTimeDuringDay2 - 1
相同时,它似乎有问题。
答案 0 :(得分:28)
问题是,我用于设置DatePicker
的{{1}}和minDate
的日历的小时,分钟,秒和毫秒被设置为对应的值调用maxDate
时的时间。当我将日,月和年传递给Calendar.getInstance()
的构造函数时,日期是相同的,但毫秒不同。因此,可能会发生maxDate中设置的毫秒小于DatePickerDialog
当前时间中设置的毫秒数,因此DatePicker
应该显示的日期被评估为大于{{1} }(即使它仍然是同一天,只需要几毫秒)......同样适用于DatePicker
。
我希望这是可以理解的。
所以有助于将日历设置为使用它们设置maxDate
的当天的最后一毫秒,以及使用它们设置minDate
时的第一个毫秒。像这样:
(只是maxDate
子句中的一段代码。)
minDate
希望对某人有所帮助。
如果有人想出更优雅的解决方案,请告诉我。
答案 1 :(得分:8)
当今天不在[minDate,maxDate]时,我得到了相同的异常。但是,如果我将代码更改为在setMinDate()
之前调用setMaxDate()
,则可以正常工作。
答案 2 :(得分:4)
为了加强上述答案,我决定发布此内容。
多次调用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());
答案 3 :(得分:2)
与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());
答案 4 :(得分:1)
这就是我在DatePicker上遇到的同样错误。所以当我在DatePicker上设置MaxDate和MinDate时,毫秒数正在改变。对于我的申请,如果日期是一秒钟,这并不重要。我需要将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);
希望这有助于某人。这将使日期设置在界限之间。您可能必须根据应用程序更改偏移量。
答案 5 :(得分:0)
我通过将日历限制设置为一年(从今天的日期开始)来解决类似的问题
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());
答案 6 :(得分:0)
就我而言,我在设置最大日期之后设置了最小日期。它会导致崩溃。
之前:
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);
}