JDK17日期格式‘MMM’导致九月Sept/Sep格式化异常问题❗❗❗
🔍 起因
JDK-8256837
As discussed in daily call , we are using the ‘YYYY-MM-DD’ as the date format , so no impact for us and it will format the year-month-date to be ‘2025-09-02’. This JDK month format issue especially happened in some HSBCnet applications because they more like to use ‘MMM’ as the month format .
- "A known bug in JDK 17, tracked as JDK-8281302, changed the short name for September from "Sep" to "Sept" when using Locale.UK for date formatting and parsing. This change specifically affects September and can cause parsing errors when dealing with historical data or external sources that still use "Sep".
- This issue is present in JDK versions 16, 17, 18, and 19. While other months retain their three-letter abbreviations, September uniquely adopted a four-letter abbreviation in this specific locale setting.
- To address this, particularly when parsing dates from external sources or legacy systems, a common workaround involves performing a string replacement, such as replacing "Sep" with "Sept" before attempting to parse the date string with SimpleDateFormat or other date/time APIs."
****** 整理 by
Moshow郑锴@https://zhengkai.blog.csdn.net/
在 JDK17 中,SimpleDateFormat
使用 "MMM"
格式时,如果 Locale 是 Locale.UK
,它只接受 "Sept"
而不是 "Sep"
,这确实是一个令人困惑的变化。
🔍 为什么必须是 "Sept"
而不是 "Sep"
这是因为:
-
SimpleDateFormat
的"MMM"
格式依赖于 Locale 的月份缩写资源。 -
在 JDK17 的
Locale.UK
中,九月的缩写是"Sept"
,而不是"Sep"
。 -
所以当你传入
"Sep"
时,它无法匹配 Locale.UK 的预期格式,从而抛出ParseException
。
这在 JDK8 中可能没有问题,因为早期版本对缩写更宽容,或者 Locale.UK 的资源不同。
✅ 解决方案
1. ✅ 改为使用 Locale.ENGLISH
DateFormat df = new SimpleDateFormat("yyyy MMM dd", Locale.ENGLISH);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = df.parse("2015 Sep 30"); // ✅ 正常解析
-
Locale.ENGLISH
的九月缩写是"Sep"
,与输入匹配。 -
这是最直接的解决方法。
2. ✅ 或者修改输入字符串为 "Sept"
DateFormat df = new SimpleDateFormat("yyyy MMM dd", Locale.UK);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = df.parse("2015 Sept 30"); // ✅ 正常解析
-
如果你坚持使用
Locale.UK
,那就必须使用"Sept"
。直接.replace("Sep","Sept")
🧠 延伸建议:避免 SimpleDateFormat
的坑
考虑使用 Java 8 引入的 DateTimeFormatter
:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MMM dd", Locale.ENGLISH);
LocalDate date = LocalDate.parse("2015 Sep 30", formatter);
-
更安全、线程安全、行为一致。
-
不容易被 Locale 的细节坑到。
如果你是在处理用户输入或日志解析,建议统一 Locale 或做预处理,比如把 "Sep"
替换成 "Sept"
,或者直接切换到 Locale.ENGLISH
。
****** 整理 by Moshow郑锴@https://zhengkai.blog.csdn.net/