SimpleDateFormat.parse()使用"YYYY/MMM/d"返回错误日期求助
问题根源:混淆了
YYYY和yyyy的区别 哈哈,这个坑我之前也踩过!你遇到的错误日期问题,核心原因就是误用了周年份格式符YYYY,而不是我们日常用的日历年份格式符yyyy。
先搞清楚两者的差异:
yyyy:这是我们熟悉的常规日历年份,对应格里高利历里的年份,就是平时说的“2019年”这种。YYYY:这个是周年份,指的是当前日期所在的周所属的年份。周年份的规则有点特殊:它的第一周是包含该年第一个“周起始日”(比如很多地区是周一,部分是周日,取决于Locale)的那一周,或者按ISO标准是包含1月4日的那一周。这就导致,年初或年末的某些日期,周年份可能和日历年份不一样(比如2019年1月1日,在ISO周规则里属于2018年的第52周)。
结合你的代码分析:
你格式化2019年4月9日时用YYYY,得到2019/Apr/9是没问题的——这一天的周年份确实是2019。但解析环节出问题了:
当你用YYYY去解析2019/Apr/9时,解析器会把2019当作周年份,但你同时提供了月份(Apr)和日期(9),这两个属于日历日期体系,和周年份体系不兼容。SimpleDateFormat在这种冲突场景下,会默认取周年份2019的第一周,然后尝试匹配你给的月日,结果就出现了日期回退到2018年12月31日的错误——因为在AST时区,2019年的第一周起始日期就是2018年12月31日。
解决方案:把YYYY改成yyyy
只需要修改格式字符串,用yyyy替代YYYY,就能让格式化和解析都正常工作:
Date date = new Date(); System.out.println(date); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MMM/d"); String dateString = simpleDateFormat.format(date); System.out.println(dateString); date = simpleDateFormat.parse(dateString); System.out.println(date);
运行这段代码,解析后的日期就会和原日期一致,不会再出现跳转到2018年的问题。
额外建议:优先使用Java 8+的新日期API
如果你的项目是Java 8及以上版本,强烈建议用java.time包下的类(比如DateTimeFormatter、LocalDate)替代SimpleDateFormat。新API设计更清晰,完全避免了这类格式符混淆的问题,而且是线程安全的,示例代码如下:
LocalDate date = LocalDate.now(); System.out.println(date); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MMM/d"); String dateString = date.format(formatter); System.out.println(dateString); date = LocalDate.parse(dateString, formatter); System.out.println(date);
内容的提问来源于stack exchange,提问作者VladislavShcherba
相关产品推荐
相关产品推荐

