API Level 23及更低版本中的奇怪java.util.Calendar行为

时间:2018-02-22 15:04:15

标签: java android android-api-levels java.util.calendar

在Android上使用java.util.Calendar时,我偶然发现了一个有趣的错误:在API级别23或更低级别Calendar.set(...)设置的某些字段在调用Calendar.get(...)之前不会应用(因为get方法在内部调用complete()?)

发生此问题,多次设置Calendar.DAY_OF_MONTH时,请查看以下代码:

DateHelper.kt

class DateHelper{
    companion object {
        fun getStartOfWeek(yearInformation : Date, weekNumber: Int, applyFix: Boolean = false): Date {
            val cal = Calendar.getInstance()
            cal.time = yearInformation
            cal.set(Calendar.WEEK_OF_YEAR, weekNumber)
            if(applyFix) cal.get(Calendar.WEEK_OF_YEAR)
            cal.set(Calendar.DAY_OF_WEEK, cal.firstDayOfWeek)
            return cal.time
        }
    }
}

DateHelperTest.kt

@RunWith(AndroidJUnit4::class) 
class DateHelperTest{

    /** setting the week of month only once works */
    @Test
    fun shouldReturnCorrectStartOfWeek(){

        val cal = Calendar.getInstance()
        cal.set(Calendar.YEAR, 2018)
        val yearInformation = cal.time

        val weeknumber = 8 //Sunday = 18.02, Monday = 19.02

        val result = DateHelper.getStartOfWeek(yearInformation, weeknumber)
        cal.time = result
        val acualDay = cal.get(Calendar.DAY_OF_MONTH)

        assertThat(acualDay, anyOf(equalTo(18), equalTo(19)))
    }

    /**
     * setting the week of month twice (calling DateHelper.getStartOfWeek multiple times)
     * doesn't work (for API level <= 23)
     */
    @Test
    fun shouldChangeStartOfWeekCorrectly(){
        val cal = Calendar.getInstance()
        cal.set(Calendar.YEAR, 2018)
        val yearInformation = cal.time

        var weeknumber = 8 //Sunday = 18.02, Monday = 19.02
        DateHelper.getStartOfWeek(yearInformation, weeknumber) //initial call

        weeknumber = 9 //incremented, Sunday = 25, Monday = 26 now
        val result = DateHelper.getStartOfWeek(yearInformation, weeknumber) //second, tested call
        cal.time = result
        val actualDay = cal.get(Calendar.DAY_OF_MONTH)
        assertThat(actualDay, anyOf(equalTo(25), equalTo(26)))
    }

    /**
     * same as shouldChangeStartOfWeekCorrectly() but with workaround
     * (internally calling cal.get())
     * */
    @Test
    fun shouldChangeStartOfWeekCorrectly_WithWorkaround(){
        val cal = Calendar.getInstance()
        cal.set(Calendar.YEAR, 2018)
        val yearInformation = cal.time

        var weeknumber = 8 //Sunday = 18.02, Monday = 19.02
        DateHelper.getStartOfWeek(yearInformation, weeknumber) //initial call

        weeknumber = 9 //incremented, Sunday = 25, Monday = 26 now

        /* date helper call changed */
        val result = DateHelper.getStartOfWeek(yearInformation, weeknumber, applyFix = true) //second, tested call
        /* date helper call changed */            

        cal.time = result
        val actualDay = cal.get(Calendar.DAY_OF_MONTH)
        assertThat(actualDay, anyOf(equalTo(25), equalTo(26)))
    }
}

Example Project on GitHub with executable instrumentation tests

提供的解决方法(if(applyFix) cal.get(Calendar.WEEK_OF_YEAR))相当不愉快:如何以正确的方式解决此问题?

0 个答案:

没有答案