17

我有一个由开始日期和结束日期组成的时间间隔。我有办法让用户通过 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而不是传递someTimeDuringDay2DatePickerDialog' 的构造函数,问题就消失了。但是然后“天”字段DatePicker确实比我想要的小一。我需要将其设置为显示someTimeDuringDay2DatePickerDialog,而不是someTimeDuringDay2 - 1. 但是当日期与它相同时,它似乎有问题maxDate

4

8 回答 8

28

问题是我用来设置DatePicker's的日历的小时、分钟、秒和毫秒,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());

希望它对某人有所帮助。

另外,如果有人提出更优雅的解决方案,请告诉我。

于 2013-03-29T06:54:36.863 回答
9

当今天不在 [minDate, maxDate] 时,我得到了同样的例外。但是,如果我将代码更改为 call setMinDate()before setMaxDate(),它就起作用了。

于 2015-11-27T10:00:48.837 回答
4

为了增强上述答案,我决定发布此内容。

当多次调用 setMaxDate() 时,假设 onPrepareDialog() 发生动态变化,您必须确保新的最大年份不等于前一个最大年份或新的最大日期等于旧的最大日期。

听起来很奇怪,但这是来自grep 代码的源代码

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());  
于 2013-08-16T17:39:48.793 回答
2

我遇到了同样的错误,我通过设置修复它

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());
于 2015-09-09T10:49:05.767 回答
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());
于 2017-02-07T22:21:32.643 回答
1

这就是我为在 DatePicker 上遇到的相同错误所做的。因此,当我在 DatePicker 上设置 MaxDate 和 MinDate 时,毫秒数正在发生变化。对于我的申请,日期是否相差一秒并不重要。我需要 mindates 和 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);

希望这可以帮助某人。这将使日期设置在界限之间。您可能必须根据您的应用程序更改偏移量。

于 2015-08-25T20:48:42.760 回答
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());
于 2016-07-05T12:42:38.030 回答
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);
}
于 2019-10-18T03:38:47.563 回答