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

Android 6设备中SimpleDateFormat解析日期字符串遇ParseException问题

问题原因及解决方案

这个问题我之前也碰到过,核心原因是不同Android版本的SimpleDateFormat解析逻辑差异,再加上设备区域设置的影响:

为什么Android 6真机报错,而Android 8和模拟器正常?

  • Android 8(API 26)及以上版本,SimpleDateFormat对AM/PM标识的解析做了兼容性优化,即便设备区域设置不是英文,也能正确识别"AM"/"PM"这类英文标识。
  • 但Android 6(API 23)及更低版本的SimpleDateFormat非常依赖系统当前的区域设置:如果你的真机系统语言不是英文,或者区域设置里的AM/PM缩写不是"AM"/"PM"(比如部分地区用"上午"/"下午"、或者其他语言的本地化缩写),就会因为无法识别字符串里的"AM"而抛出ParseException。
  • 模拟器通常默认是英文区域设置,所以能正常解析,这就是为什么模拟器没问题但真机报错的原因。

另外你代码里还有个小问题:var date = formatter.parse(date)里的变量名重复了(date既是输入的字符串变量,又是要赋值的Date对象),虽然编译器可能不会报错,但容易引起混淆,建议修改变量名,比如把输入字符串改成dateString。

解决方案

方案1:给SimpleDateFormat指定英文Locale(快速修复)

创建SimpleDateFormat时明确传入Locale.ENGLISH,强制解析逻辑使用英文的AM/PM规则,这样不管设备的区域设置是什么,都能正确识别"AM"/"PM":

val dateString = "10/10/2016 12:00:00 AM"
val formatter = SimpleDateFormat("MM/dd/yyyy hh:mm:ss aa", Locale.ENGLISH)
val date = formatter.parse(dateString)

方案2:使用更稳定的日期时间库(推荐)

SimpleDateFormat本身是线程不安全的,而且在不同Android版本的行为不一致,Google官方推荐使用ThreeTenABP(适配Android的JSR-310日期时间库),它能统一所有Android版本的日期解析行为:

  1. 首先在你的build.gradle(Module级别)添加依赖:
implementation 'com.jakewharton.threetenabp:threetenabp:1.4.6'
  1. 在自定义的Application类的onCreate方法中初始化库:
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        ThreeTenABP.init(this)
    }
}
  1. 然后用以下代码解析日期:
val dateString = "10/10/2016 12:00:00 AM"
val formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a", Locale.ENGLISH)
val localDateTime = LocalDateTime.parse(dateString, formatter)
// 如果需要转换为Date对象(兼容旧代码):
val date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant())

为什么移除AM/PM能解决问题?

当你去掉格式化字符串里的aa部分后,解析逻辑只需要处理日期和时间的数字部分,不需要识别和区域设置相关的AM/PM标识,自然就不会因为区域不匹配而抛出异常了。

内容的提问来源于stack exchange,提问作者Luis Abreu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:59:14