使用ZonedDateTime与DateTimeFormatter解析日期时间结果不一致问题
问题
以下代码中,待解析的日期时间字符串完全相同,但通过两种方式创建的DateTimeFormatter解析后得到的Epoch时间不一致:
public class DateTimeFormatterUtilsTest { private static final String ISO_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; private static final String ISO_DATETIME_TO_PARSE = "2007-12-03T10:15:30.000Z"; private static final long TARGET_EPOCH_TIME = 1196676930000L; @Test public void testDateTimeFormatterUtils() { ZoneId targetZoneid = TimeUtils.getZoneId(TIMEZONE.PST); DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT.withZone(targetZoneid); long epochTime = parseDateTime(ISO_DATETIME_TO_PARSE, formatter); assertTrue(epochTime == TARGET_EPOCH_TIME); // specify custom pattern DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern(ISO_DATETIME_PATTERN).withZone(targetZoneid); epochTime = parseDateTime(ISO_DATETIME_TO_PARSE, formatter1); assertTrue(epochTime == TARGET_EPOCH_TIME); } public long parseDateTime(final String dateTimeString, DateTimeFormatter formatter) { ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateTimeString, formatter); System.out.println("parsed zoned date time" + zonedDateTime); Instant instant = zonedDateTime.toInstant(); long epochTime = instant.toEpochMilli(); System.out.println("Epoch time for" + ISO_DATETIME_TO_PARSE + "is " + epochTime); return epochTime; } }
使用DateTimeFormatter.ISO_INSTANT时得到正确的Epoch时间1196676930000,但使用自定义模式创建的formatter1得到的Epoch时间为1196705730000,两者相差8小时(28800000毫秒),请问该现象的原因是什么?
原因分析
核心差异在于对字符串中Z的解析逻辑:
DateTimeFormatter.ISO_INSTANT中的Z是时区标识,代表UTC零时区。解析时会将字符串里的Z识别为UTC时间标记,后续即使调用withZone(targetZoneid)转换时区,最终转成Instant时仍会还原为UTC对应的Epoch时间,结果正确。- 自定义模式
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"里的'Z'是字面量字符,仅作为普通字符串匹配,不具备时区语义。解析器会把2007-12-03T10:15:30.000直接当作目标时区(PST西八区)的本地时间,转成Instant时会加上8小时的时区偏移,导致Epoch时间比正确值多出8小时。
内容的提问来源于stack exchange,提问作者blue mountain
相关产品推荐
相关产品推荐

