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

SimpleDateFormat转换GMT ISO8601时间戳为Unix epoch失败怎么办

问题背景

需要解析符合ISO8601规范的GMT时间戳:2022-01-12T17:17:34.512492+0000,目标转换为Unix epoch时间,使用java.text.SimpleDateFormat实现时两种方案均无法得到正确结果:

错误方案1

  • 实现代码:
val parsed = "2022-01-12T17:17:34.512492+0000"
val df: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'ZZZZ'")
val date = df.parse(parsed.toString)
val epoch = date.getTime
  • 运行异常:java.text.ParseException: Unparseable date: "2022-01-12T17:17:34.512492+0000"

错误方案2

  • 实现代码:
val parsed = "2022-01-12T17:17:34.512492+0000"
val df: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'+0000'")
val date = df.parse(parsed.toString)
val epoch = date.getTime
println(epoch)
  • 运行输出epoch值:1642004766492
  • 错误表现:将该epoch值转换为可读日期为Wednesday, 12 January 2022 16:26:06.492,时、分、秒数值与原时间戳完全不符。
问题根源

两种方案失败的核心原因有两个:

  • SimpleDateFormat格式串中单引号包裹的内容为字面量匹配规则:第一种方案用'ZZZZ'表示匹配字符串中连续的ZZZZ四个字符,和时间戳末尾实际的+0000完全不匹配,因此直接抛出解析异常。
  • SimpleDateFormat的S模式符仅支持毫秒(3位长度)解析,不支持6位微秒级精度:写6个S时,解析器会将.512492识别为512492毫秒,换算后额外叠加了数百秒的时间偏移,直接导致时分秒结果错误。同时第二种方案将+0000写死为字面量,遇到其他时区偏移的时间戳会直接解析失败,无通用性。
正确解决方案

方案1:Java 8+ 标准时间API(推荐,无第三方依赖)

Java 8开始内置的java.time包(JSR310规范)原生支持ISO8601格式和纳秒级精度解析,不需要手动编写复杂格式串,代码最简洁、容错性最高:

import java.time.OffsetDateTime

val parsed = "2022-01-12T17:17:34.512492+0000"
// 原生识别ISO8601格式,自动解析6位微秒和时区偏移
val offsetDateTime = OffsetDateTime.parse(parsed)
// 转换为Unix epoch毫秒值,与Date.getTime()返回语义完全一致
val epoch = offsetDateTime.toInstant.toEpochMilli

运行得到正确epoch值为1642007854512,转回UTC时间为2022-01-12T17:17:34.512Z,与原时间戳完全匹配。

如果需要解析非标准格式的同类时间戳,可以使用DateTimeFormatter自定义匹配规则,它的S模式符支持任意长度的秒小数解析:

import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter

val parsed = "2022-01-12T17:17:34.512492+0000"
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXX")
val offsetDateTime = OffsetDateTime.parse(parsed, formatter)
val epoch = offsetDateTime.toInstant.toEpochMilli

方案2:兼容旧版本Java的SimpleDateFormat实现

如果受环境限制只能使用SimpleDateFormat,需要先将时间串中的6位微秒截断为3位毫秒,再使用正确的时区匹配规则解析:

import java.text.SimpleDateFormat
import java.util.TimeZone

val parsed = "2022-01-12T17:17:34.512492+0000"
// 正则截断6位小数秒为3位,保留原时区偏移
val adjustedTimeStr = parsed.replaceAll("(\\.\\d{3})\\d{3}([+-]\\d{4})", "$1$2")
val df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
// 显式设置UTC时区避免系统默认时区干扰解析结果
df.setTimeZone(TimeZone.getTimeZone("UTC"))
val date = df.parse(adjustedTimeStr)
val epoch = date.getTime

该方案可以得到正确的毫秒级epoch值,但会丢失微秒精度,且正则匹配对非标准格式时间串兼容性差,优先使用方案1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 14:27:17