Java中SimpleDateFormat解析时间戳出现时差异常的原因咨询
问题原因分析与解决方案
这个异常的核心问题出在你使用的日期格式符上——你用了12小时制的hh,但输入的时间是24小时制的数值,导致解析逻辑完全跑偏了!
具体细节拆解:
- 在
SimpleDateFormat的规则里,hh代表的是12小时制的小时(取值范围是1-12),而HH才是24小时制的小时(取值范围0-23)。 - 当你解析
2020-04-06T12:52:38+0000时,hh会把这个12识别为12小时制的「午夜12点」(也就是24小时制的00:00)。再加上EDT时区和UTC的时差是-4小时,UTC的00:00减去4小时就是前一天的20:52,这就导致了看起来像13小时时差的错误结果。 - 另外你输入的
2020-04-06T24:52:38+0000本身是不符合时间规范的:24小时制里的小时最大是23,24:52这种写法是非法的。SimpleDateFormat在这里做了「宽容」处理,自动把24点进位成了次日的00点,所以解析后得到了Mon Apr 06 20:52:38 EDT 2020(UTC次日00:52减去4小时就是EDT的当天20:52)。
修复方案:
- 修正格式符:把日期格式字符串改成
"yyyy-MM-dd'T'HH:mm:ssZ",用HH(24小时制)替换hh(12小时制)。修正后代码如下:
public static void main(String args[]) { List<String> list = new ArrayList<>(); list.add("2020-04-06T00:52:38+0000"); list.add("2020-04-06T24:52:38+0000"); // 注意:这个时间本身非法,建议改成2020-04-07T00:52:38+0000 list.add("2020-04-06T12:52:38+0000"); Date createdTime = null; DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); try { for (int i =0; i < list.size(); i++) { createdTime = df.parse(list.get(i)); System.out.print(i + " : " + "Media Created_on : " + createdTime + "\n"); } } catch (ParseException e) { e.printStackTrace(); } }
- 推荐使用Java 8+的新时间API:
SimpleDateFormat是线程不安全的,而且对非法时间的宽容处理容易隐藏问题。建议改用java.time包下的DateTimeFormatter和ZonedDateTime,它会严格验证时间合法性,比如遇到24:52这种非法值会直接抛出异常,便于你提前发现问题:
public static void main(String args[]) { List<String> list = List.of( "2020-04-06T00:52:38+0000", "2020-04-07T00:52:38+0000", // 修正后的合法时间 "2020-04-06T12:52:38+0000" ); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); for (int i = 0; i < list.size(); i++) { try { ZonedDateTime zonedDateTime = ZonedDateTime.parse(list.get(i), formatter); System.out.printf("%d : Media Created_on : %s%n", i, zonedDateTime.withZoneSameInstant(ZoneId.of("America/New_York"))); } catch (DateTimeParseException e) { System.err.printf("%d : 时间解析失败:%s%n", i, e.getMessage()); } } }
内容的提问来源于stack exchange,提问作者keeru
相关产品推荐
相关产品推荐

