Android Kotlin/Java中如何解析ISO8601格式日期时间
问题根因
解析抛出异常的直接原因是定义的日期格式匹配规则,和实际输入的日期字符串结构完全不匹配,具体错误点如下:
- 输入字符串
"20220610T230000Z"是ISO 8601的基础无分隔符格式,结构为4位年+2位月+2位日+字符T+2位时+2位分+2位秒+末尾Z(代表UTC零时区),全程没有时间分隔冒号、没有毫秒字段 - 原有匹配规则
"yyyymmdd'T'HH:mm:ss.SSS'Z'"存在多处错误:- 年份占位符仅写了3个
y,实际输入为4位年份,需要写yyyy - 用代表分钟的小写
mm匹配月份,正确的月份占位符为大写MM - 额外加了输入中不存在的时分秒分隔符冒号
:、毫秒段.SSS - 把时区标识
Z用单引号包裹为普通字面量,不仅会导致匹配失败,就算调整后能解析也会丢失时区信息,得到错误的时间值
- 年份占位符仅写了3个
正确实现方案
方案1:使用java.time API(推荐)
JDK 8及以上版本、安卓开启核心库脱糖后可直接使用,相比老旧的SimpleDateFormat线程安全、时区处理逻辑清晰、无隐式坑。该API内置了无分隔符ISO8601格式的匹配器,无需手动拼写匹配规则:
import java.time.Instant import java.time.format.DateTimeFormatter import java.time.ZoneId val isoDate = "20220610T230000Z" // 扫码得到的原始时间串 // 直接解析为UTC时间点 val utcInstant = Instant.from(DateTimeFormatter.BASIC_ISO_DATE_TIME.parse(isoDate)) // 按需自定义展示格式,例:转东八区时间按 yyyy-MM-dd HH:mm:ss 展示 val showFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") .withZone(ZoneId.of("Asia/Shanghai")) val displayTime = showFormatter.format(utcInstant) // 输出结果:2022-06-11 07:00:00,对应UTC时间23点加8小时偏移,时间准确
方案2:使用SimpleDateFormat(兼容老旧环境)
如果必须使用老旧日期API,需要严格匹配输入字符串结构,同时正确处理时区:
import java.text.SimpleDateFormat import java.util.Locale import java.util.TimeZone val isoDate = "20220610T230000Z" // 匹配规则严格对齐输入结构:无冒号、无毫秒、用X匹配ISO时区标识Z val sdf = SimpleDateFormat("yyyyMMdd'T'HHmmssX", Locale.getDefault()) // 强制设置格式化器时区为UTC,避免本地时区默认值干扰解析结果 sdf.timeZone = TimeZone.getTimeZone("UTC") val date = sdf.parse(isoDate)
注意事项
- 日期解析的核心要求是匹配规则必须和输入字符串的字段顺序、分隔符、字段长度完全一一对应,多一个或少一个字符都会触发解析失败
- 不要将时区标识用单引号包裹为普通字符,否则会丢失时区信息,导致解析出的时间和实际值存在时区偏移差
内容的提问来源于stack exchange,提问作者Ahmed Saad
相关产品推荐
相关产品推荐

