谁能解释为什么4个日历中的1个显示Time =?

时间:2019-07-10 16:33:51

标签: java android calendar

我有4个日历,分别是startCal,endCal,alerterCal和今天。今天只需获取当前日期/时间的Calendar.getInstance(),而其他3个则通过相同的方法使用Android的日期/时间选择器选择日期和时间。

startCal和endCal运行正常     if(startCal.after(endCal)){//处理错误}

但是,即使我故意在当前日期之前设置了hinterCal,alerterCal.before(今天)也不会返回true。

此外,在所有时间打印时,hinterCal没有任何时间(Time =?)和areFieldsSet = false,但是如果我第二次提交时间,则更新时间,尽管before()方法仍然没有工作!

除了else if if(reminderCal.before(today))以外,其他一切似乎都可以正常工作

public boolean validInput(){
    if(startCal.after(endCal)){
        //THIS WORKS
        timeError.setText(getString(R.string.error_event_end_early));
        isOk = false;
        Log.e(TAG, "validInput: Event ends before it starts");
    }

    if(hasReminder.isChecked()){
        if(reminderDate.getText().toString().matches("")) {
            // THIS WORKS
            reminderError.setText(R.string.error_no_reminder);
            isOk = false;
            Log.e(TAG, "validInput: No reminder set");
        } else if (reminderCal.before(today)){
            // THIS DOESN'T WORK. Why?
            reminderError.setText(R.string.error_reminder_early);
            isOk = false;
            Log.e(TAG, "validInput: Reminder too early " + reminderCal.toString());
        }  else if(reminderCal.after(startCal)){
            //THIS WORKS
            reminderError.setText(R.string.error_reminder_late);
            isOk = false;
            Log.e(TAG, "validInput: Reminder too late");
        }
    return isOk;
}


    Log.e(TAG, "Debugging: \n" +
            "strCalandar: " + startCal.toString() + "\n" +
            "endCalandar: " + endCal.toString() + "\n" +
            "remCalandar: " + reminderCal.toString() + "\n" +
            "todCalandar: " + today.toString() + "\n");
}

今天= Calander.getInstance();没有进一步的调整。其他日历通过这些方法获取日期/时间。

public void showDatePickerDialog(final EditText text, final Calendar cal){
    Log.d(TAG, "showDatePickerDialog: Open");
    DialogFragment datePicker = new DatePickerFragment();
    ((DatePickerFragment) datePicker).setOnDateChosenListener(new DatePickerFragment.OnDateChosenListener() {
        @Override
        public void onDateChosen(int year, int month, int day) {
            text.setText(String.format("%02d/%02d/%04d", day, month, year));
            cal.set(year, month, day);
        }
    });
    datePicker.show(getSupportFragmentManager(), "DatePicker");
}

public void showTimePickerDialog(final EditText text, final Calendar cal){
    Log.d(TAG, "showTimePickerDialog: Open");
    DialogFragment timePicker = new TimePickerFragment();
    ((TimePickerFragment) timePicker).setOnTimeChosenListener(new TimePickerFragment.OnTimeChosenListener() {
        @Override
        public void onTimeChosen(int hour, int min) {
            text.setText(String.format("%02d:%02d", hour, min));
            cal.set(Calendar.HOUR_OF_DAY, hour);
            cal.set(Calendar.MINUTE, min);
        }
    });
    timePicker.show(getSupportFragmentManager(), "TimePicker");
}

Logcat中的输出:

strCalandar: java.util.GregorianCalendar[time=1566152201478,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=libcore.util.ZoneInfo[id="Europe/London",mRawOffset=0,mEarliestRawOffset=0,mUseDst=true,mDstSavings=3600000,transitions=242],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2019,MONTH=7,WEEK_OF_YEAR=33,WEEK_OF_MONTH=3,DAY_OF_MONTH=18,DAY_OF_YEAR=230,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=16,SECOND=41,MILLISECOND=478,ZONE_OFFSET=0,DST_OFFSET=3600000]
endCalandar: java.util.GregorianCalendar[time=1566152201478,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=libcore.util.ZoneInfo[id="Europe/London",mRawOffset=0,mEarliestRawOffset=0,mUseDst=true,mDstSavings=3600000,transitions=242],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2019,MONTH=7,WEEK_OF_YEAR=33,WEEK_OF_MONTH=3,DAY_OF_MONTH=18,DAY_OF_YEAR=230,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=16,SECOND=41,MILLISECOND=478,ZONE_OFFSET=0,DST_OFFSET=3600000]
remCalandar: java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=libcore.util.ZoneInfo[id="Europe/London",mRawOffset=0,mEarliestRawOffset=0,mUseDst=true,mDstSavings=3600000,transitions=242],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2019,MONTH=7,WEEK_OF_YEAR=31,WEEK_OF_MONTH=1,DAY_OF_MONTH=2,DAY_OF_YEAR=214,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=5,HOUR_OF_DAY=17,MINUTE=18,SECOND=41,MILLISECOND=478,ZONE_OFFSET=0,DST_OFFSET=3600000]
todCalandar: java.util.GregorianCalendar[time=1562775401478,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=libcore.util.ZoneInfo[id="Europe/London",mRawOffset=0,mEarliestRawOffset=0,mUseDst=true,mDstSavings=3600000,transitions=242],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2019,MONTH=6,WEEK_OF_YEAR=28,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=191,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=5,HOUR_OF_DAY=17,MINUTE=16,SECOND=41,MILLISECOND=478,ZONE_OFFSET=0,DST_OFFSET=3600000]
如果提醒日期设置为当前日期之前,

reminderCal.before(today)应该返回true

1 个答案:

答案 0 :(得分:1)

他们试图在文档的这一部分中对此进行解释:

  

set(f, value) 将日历字段f更改为value。此外,它设置一个内部成员变量以指示   日历字段f已更改。尽管日历字段f为   立即更改,日历的时间值(以毫秒为单位)不是   重新计算直到下一次调用get()getTime(),   制作了getTimeInMillis()add()roll()。因此,多个   调用set()不会触发多个不必要的计算。如   使用set()和其他日历更改日历字段的结果   字段也可能会更改,具体取决于日历字段   字段值和日历系统。此外,get(f)不会   必须返回通过调用set方法后设置的值   日历字段已重新计算。具体取决于   具体的日历类。

     

示例:考虑最初设置为1999年8月31日的GregorianCalendar。调用set(Calendar.MONTH,Calendar.SEPTEMBER)将日期设置为1999年9月31日。这是一个临时内部表示形式,它   如果随后调用getTime(),则解析为1999年10月1日。但是,   在调用getTime()之前调用set(Calendar.DAY_OF_MONTH,30)   将日期设置为1999年9月30日,因为没有重新计算   在set()本身之后。

因此,由于您分别调用cal.set(Calendar.HOUR_OF_DAY, hour);cal.set(Calendar.MINUTE, min);,所以时间暂时不确定,这就是为什么从toString打印问号的原因。

我无法重现beforeafter的举报行为,但是假设它们在get或其中之一无法正常工作之前似乎是合理的。提到的getXxx方法被调用。

这只是Calendar类设计中非常令人困惑的方面之一。好的解决方案是切换到使用java.time, the modern Java date and time API