Java 8与Java 11中Instant.toEpochMilli结果不一致问题求助
Java 8与Java 11中DateTimeFormatter解析带时区日期生成的时间戳不一致
问题详情
以下代码在Java 8和Java 11运行时,输出的epoch毫秒时间戳结果不一致:
String strDate = "2022-07-18 17:52:23 America/New_York"; DateTimeFormatter frmt = new DateTimeFormatterBuilder() .appendPattern("yyyy-MM-dd HH:mm:ss VV") .parseDefaulting(ChronoField.HOUR_OF_DAY,0) .parseDefaulting(ChronoField.MINUTE_OF_HOUR,0) .parseDefaulting(ChronoField.SECOND_OF_MINUTE,0) .parseDefaulting(ChronoField.NANO_OF_SECOND,0) .parseDefaulting(ChronoField.OFFSET_SECONDS,0) .toFormatter(); TemporalAccessor temporal = frmt.parse(strDate); System.out.println(Instant.from(temporal).toEpochMilli());
输出差异
- Java 8:
1658181143000(对应纽约时区的正确时间戳) - Java 11:
1658166743000(错误,对应UTC时区的时间戳)
问题原因
问题出在parseDefaulting(ChronoField.OFFSET_SECONDS,0)这一行:
- Java 8中,解析到
VV(时区ID)时,会自动计算该时区对应的偏移量,并覆盖默认设置的OFFSET_SECONDS值; - Java 11调整了解析逻辑的优先级,显式设置的
OFFSET_SECONDS默认值会优先生效,导致解析时忽略了从America/New_York时区ID获取的实际偏移量,强制使用UTC偏移(0秒)。
解决方案
移除parseDefaulting(ChronoField.OFFSET_SECONDS,0)这一行即可。通过VV模式解析出的时区ID已经包含该时区的正确偏移信息,无需额外设置默认偏移量。
修改后的代码:
String strDate = "2022-07-18 17:52:23 America/New_York"; DateTimeFormatter frmt = new DateTimeFormatterBuilder() .appendPattern("yyyy-MM-dd HH:mm:ss VV") .parseDefaulting(ChronoField.HOUR_OF_DAY,0) .parseDefaulting(ChronoField.MINUTE_OF_HOUR,0) .parseDefaulting(ChronoField.SECOND_OF_MINUTE,0) .parseDefaulting(ChronoField.NANO_OF_SECOND,0) .toFormatter(); TemporalAccessor temporal = frmt.parse(strDate); System.out.println(Instant.from(temporal).toEpochMilli());
验证结果
修改后,Java 8和Java 11均输出正确的纽约时区对应时间戳:1658181143000
内容的提问来源于stack exchange,提问作者Mathew Mani
相关产品推荐
相关产品推荐

