0

java.util.CalendarAndroid 上使用时,我偶然发现了一个有趣的错误:在 API 级别 23 或更低级别上,某些由设置的字段在调用Calendar.set(...)之前不会应用Calendar.get(...)(因为 get-method 内部调用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)))
    }
}

GitHub 上带有可执行仪器测试的示例项目

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

4

0 回答 0