You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

java.time月份拼写Bug规避方案咨询:September显示为Sept问题

JDK java.time 9月缩写Bug的规避方案

问题背景

在JDK 17.0.10、JDK 21.0.4版本(涵盖MacOS X和Centos Stream 9系统)中,使用DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy")格式化9月日期时,会错误输出Sept而非预期的Sep;反序列化标准Sep格式字符串时,会抛出DateTimeParseException,导致Gson反序列化失败。该Bug已上报至Oracle Bug数据库(ID:9077542),短期内无法修复,需手动规避。

可行规避方案

方案1:自定义月份缩写映射的DateTimeFormatter

通过DateTimeFormatterBuilder手动指定所有月份的缩写,强制9月使用Sep,从根源上统一格式化与解析行为:

public class EuDateTimeDeserializer implements JsonDeserializer<LocalDateTime> {
    // 自定义月份缩写映射
    private static final Map<Long, String> MONTH_ABBREVIATIONS = new HashMap<>();
    static {
        MONTH_ABBREVIATIONS.put(1L, "Jan");
        MONTH_ABBREVIATIONS.put(2L, "Feb");
        MONTH_ABBREVIATIONS.put(3L, "Mar");
        MONTH_ABBREVIATIONS.put(4L, "Apr");
        MONTH_ABBREVIATIONS.put(5L, "May");
        MONTH_ABBREVIATIONS.put(6L, "Jun");
        MONTH_ABBREVIATIONS.put(7L, "Jul");
        MONTH_ABBREVIATIONS.put(8L, "Aug");
        MONTH_ABBREVIATIONS.put(9L, "Sep"); // 强制指定9月缩写为Sep
        MONTH_ABBREVIATIONS.put(10L, "Oct");
        MONTH_ABBREVIATIONS.put(11L, "Nov");
        MONTH_ABBREVIATIONS.put(12L, "Dec");
    }

    private static final DateTimeFormatter CUSTOM_FORMATTER = new DateTimeFormatterBuilder()
            .appendPattern("EEE ")
            .appendText(ChronoField.MONTH_OF_YEAR, MONTH_ABBREVIATIONS)
            .appendPattern(" dd HH:mm:ss yyyy")
            .toFormatter(Locale.ENGLISH); // 指定Locale,避免系统默认设置影响

    @Override
    public LocalDateTime deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
        String dateTimeStr = jsonElement.getAsString();
        if (!ThssUtils.isValidString(dateTimeStr)) {
            return null;
        }
        return LocalDateTime.parse(dateTimeStr, CUSTOM_FORMATTER);
    }

    // 格式化输出时也使用该自定义Formatter,保证输出一致性
    public static String format(LocalDateTime dateTime) {
        return CUSTOM_FORMATTER.format(dateTime);
    }
}

方案2:字符串预处理兼容两种缩写

在解析前对日期字符串进行替换,同时兼容Sep和Sept两种格式;格式化输出时也修正错误的Sept:

public class EuDateTimeDeserializer implements JsonDeserializer<LocalDateTime> {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy", Locale.ENGLISH);

    @Override
    public LocalDateTime deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
        String dateTimeStr = jsonElement.getAsString();
        if (!ThssUtils.isValidString(dateTimeStr)) {
            return null;
        }
        // 替换Sept为Sep,兼容两种格式
        String processedStr = dateTimeStr.replace("Sept", "Sep");
        return LocalDateTime.parse(processedStr, FORMATTER);
    }

    // 格式化时修正Bug导致的错误输出
    public static String format(LocalDateTime dateTime) {
        String formatted = FORMATTER.format(dateTime);
        return formatted.replace("Sept", "Sep");
    }
}

方案3:使用可选模式匹配两种缩写

通过DateTimeFormatterBuilder添加可选的月份缩写模式,同时支持Sep和Sept两种格式:

public class EuDateTimeDeserializer implements JsonDeserializer<LocalDateTime> {
    private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
            .appendPattern("EEE ")
            .appendOptional(DateTimeFormatter.ofPattern("Sep"))
            .appendOptional(DateTimeFormatter.ofPattern("Sept"))
            .appendPattern(" dd HH:mm:ss yyyy")
            .toFormatter(Locale.ENGLISH);

    @Override
    public LocalDateTime deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
        String dateTimeStr = jsonElement.getAsString();
        if (!ThssUtils.isValidString(dateTimeStr)) {
            return null;
        }
        return LocalDateTime.parse(dateTimeStr, FORMATTER);
    }
}

注:需注意模式顺序,优先匹配3字符缩写以避免解析歧义。

总结

优先推荐方案1,它从根源上统一了月份缩写格式,避免字符串替换可能带来的意外问题;如果仅需临时兼容现有数据,方案2实现更简单、成本更低。

内容的提问来源于stack exchange,提问作者cidy.long

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:48:17