Android中Kotlin用SDF解析带Z的日期字符串为毫秒时解析失败
问题原因
你的日期格式字符串未匹配输入末尾的Z字符,SimpleDateFormat在遇到不匹配的内容时会提前终止解析,抛出ParseException。输入字符串是2024-01-17T20:14:29.819Z,而你定义的格式yyyy-MM-dd'T'HH:mm:ss.SSS缺少对末尾Z的处理,导致解析失败。
解决方案
方案1:修改SimpleDateFormat格式(仅作兼容,不推荐)
调整格式字符串以匹配Z,有两种处理方式:
- 若
Z是固定字面量(不处理时区),用单引号包裹Z:
private fun dateToMilliseconds(dateValue: String): Long? { val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") sdf.timeZone = TimeZone.getTimeZone("UTC") // 可选,确保时区解析一致 return try { sdf.parse(dateValue)?.time } catch (e: Exception) { e.printStackTrace() null } }
- 若要正确识别
Z代表UTC时区,使用X格式符(对应ISO 8601时区标识):
private fun dateToMilliseconds(dateValue: String): Long? { val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX") return try { sdf.parse(dateValue)?.time } catch (e: Exception) { e.printStackTrace() null } }
注意:SimpleDateFormat存在线程安全问题,禁止在多线程环境下复用同一个实例。
方案2:使用现代日期时间API(推荐)
Android API 26及以上原生支持Java 8的java.time包,低版本可通过开启Core Library Desugaring或引入ThreeTenABP库实现,该方式无线程安全问题,可读性与稳定性更强:
代码示例(API 26+)
直接使用标准ISO_INSTANT格式解析:
private fun dateToMilliseconds(dateValue: String): Long? { val formatter = DateTimeFormatter.ISO_INSTANT return try { Instant.from(formatter.parse(dateValue)).toEpochMilli() } catch (e: Exception) { e.printStackTrace() null } }
或自定义格式解析:
private fun dateToMilliseconds(dateValue: String): Long? { val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX") return try { ZonedDateTime.parse(dateValue, formatter).toInstant().toEpochMilli() } catch (e: Exception) { e.printStackTrace() null } }
低版本Android配置(Core Library Desugaring)
在Module级别的build.gradle中添加如下配置:
android { defaultConfig { multiDexEnabled true // 按需开启 } compileOptions { coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" } } dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' }
内容的提问来源于stack exchange,提问作者WISHY
相关产品推荐
相关产品推荐

