SimpleDateFormat日期解析异常:四月被解析为一月的技术问询
为什么SimpleDateFormat解析"Apr 27, 2018, Fri"会得到Jan 05, 2018?
这个问题的核心坑点就是你用了YYYY而不是yyyy来表示年份——这俩格式符看起来像双胞胎,但含义差远了!
先搞懂YYYY和yyyy的本质区别
yyyy是我们日常认知里的日历年,也就是从1月1日到12月31日的公历年,完全符合我们对“年份”的常规理解。YYYY是周年份(Week-Based Year),它基于ISO周历规则:一年的第一周是包含该年至少4天的那一周(或者说包含1月4日的那一周),周年份的起止是围绕周来划分的,和日历年的起止不一定重合。比如Locale.US下一周从周日开始,2018年的第一周是2017年12月31日到2018年1月6日,1月5日就是这一周的周五。
为什么解析会出现离谱的结果?
当你在格式字符串里同时混用MMM dd(月份+日历年日期)和YYYY(周年份)时,SimpleDateFormat的解析逻辑直接混乱了:它会把"2018"当成周年份,然后试图匹配"Apr 27"和"Fri",但周年份的日期体系和日历年的月份日期根本不兼容,最后就错误地定位到了周年份2018里的第一个周五——也就是2018年1月5日。
快速解决办法
把格式字符串里的YYYY换成yyyy就行,用日历年的格式符才符合你这个日期字符串的逻辑:
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy, EEE", Locale.US); System.out.println(sdf.format(new Date())); System.out.println(sdf.format(sdf.parse("Apr 27, 2018, Fri")));
运行后输出就完全符合预期了:
Apr 27, 2018, Fri Apr 27, 2018, Fri
额外建议(避坑指南)
如果你用的是Java 8及以上版本,真心建议放弃SimpleDateFormat,改用java.time包下的新日期API(比如DateTimeFormatter、LocalDate)。它不仅天生线程安全,还把这些容易混淆的概念划分得更清晰,从根源上避免踩这类坑:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd, yyyy, EEE", Locale.US); LocalDate date = LocalDate.parse("Apr 27, 2018, Fri", formatter); System.out.println(formatter.format(date)); // 输出 Apr 27, 2018, Fri
内容的提问来源于stack exchange,提问作者user9709261
相关产品推荐
相关产品推荐

