You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NumberPicker展示日期时遇LocalDate日期值无效异常的求助

解决LocalDate转换时的DayOfMonth无效值异常

问题场景

使用NumberPicker展示日期,核心代码如下:

val numberPicker = binding.numberPicker
val values = getArrayDates(date.toString()) //EventsBottomSheet.kt:45
numberPicker.minValue = 0
numberPicker.maxValue = values.size - 1
numberPicker.displayedValues = values.toArray(arrayOfNulls<String>(values.size))
numberPicker.wrapSelectorWheel = true
numberPicker.setOnValueChangedListener { _, _, newVal ->
    binding.dateText.text = newVal.toString()
}

getArrayDates方法实现:

private fun getArrayDates(referenceDate : String) : ArrayList<String>{
    val datesList = referenceDate.split("/")
    val localeDate = LocalDate.of(datesList[0].toInt(), Month.of(datesList[1].toInt()), datesList[2].toInt()) //EventsBottomSheet.kt:65 (related with exception)
    val monthsToDisplay = listOf(localeDate.minusMonths(1), localeDate, localeDate.plusMonths(1))
    val daysList = ArrayList<String>()
    val formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
    for (month in monthsToDisplay) {
        val yearMonth = YearMonth.from(month)
        for (day in 1..yearMonth.lengthOfMonth()) {
            daysList.add(yearMonth.atDay(day).format(formatter))
        }
    }
    return daysList
}

观测到date值格式为"21/05/2023"(日/月/年),转换为LocalDate时抛出异常:

FATAL EXCEPTION: main
Process: com.ahmetkaan.kediy, PID: 19391
j$.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 2023
    at j$.time.temporal.ValueRange.checkValidValue(ValueRange.java:311)
    at j$.time.temporal.ChronoField.checkValidValue(ChronoField.java:713)
    at j$.time.LocalDate.of(LocalDate.java:250)
    at com.ahmetkaan.kediy.EventsBottomSheet.getArrayDates(EventsBottomSheet.kt:65)
    ...

已排除前导零、日期合法性问题(date在之前Fragment中由LocalDate定义)。

异常原因

异常提示DayOfMonth传入了2023,核心问题是参数顺序完全颠倒:

  • LocalDate.of(year, month, dayOfMonth)的参数顺序是「年、月、日」
  • 但拆分"21/05/2023"后,datesList[0]是日(21)、datesList[1]是月(05)、datesList[2]是年(2023),你却把年份传给了dayOfMonth参数,触发无效值异常。

解决方案

方案1:直接修正参数顺序

调整LocalDate.of的参数,匹配日/月/年的格式:

// 修正参数顺序:年(datesList[2])、月(datesList[1])、日(datesList[0])
val localeDate = LocalDate.of(datesList[2].toInt(), Month.of(datesList[1].toInt()), datesList[0].toInt())

方案2:用DateTimeFormatter解析(更规范)

手动拆分字符串容易出错,推荐用格式化器直接解析符合格式的字符串:

private fun getArrayDates(referenceDate : String) : ArrayList<String>{
    // 定义日/月/年的格式器
    val formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
    val localeDate = LocalDate.parse(referenceDate, formatter)
    
    val monthsToDisplay = listOf(localeDate.minusMonths(1), localeDate, localeDate.plusMonths(1))
    val daysList = ArrayList<String>()
    val displayFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
    for (month in monthsToDisplay) {
        val yearMonth = YearMonth.from(month)
        for (day in 1..yearMonth.lengthOfMonth()) {
            daysList.add(yearMonth.atDay(day).format(displayFormatter))
        }
    }
    return daysList
}

方案3:直接传递LocalDate(最优)

既然date本身就是LocalDate类型,完全没必要转成字符串再解析,直接传LocalDate能彻底避免格式问题:

// 调用时直接传LocalDate
val values = getArrayDates(date)

// 修改方法参数为LocalDate
private fun getArrayDates(referenceDate : LocalDate) : ArrayList<String>{
    val monthsToDisplay = listOf(referenceDate.minusMonths(1), referenceDate, referenceDate.plusMonths(1))
    val daysList = ArrayList<String>()
    val formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
    for (month in monthsToDisplay) {
        val yearMonth = YearMonth.from(month)
        for (day in 1..yearMonth.lengthOfMonth()) {
            daysList.add(yearMonth.atDay(day).format(formatter))
        }
    }
    return daysList
}

内容的提问来源于stack exchange,提问作者Ahmet Kaan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 04:37:09