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

JFormattedTextField使用双位数年份DateFormatter的世纪偏移问题咨询

最优方案:保留Locale格式的同时替换双位年份为四位

该方案完全符合用户自定义Locale的需求,不需要硬编码全局日期格式,也不受百年区间限制:

  • 从用户指定Locale的DateFormat实例中获取原生格式模板,将模板中的双位年份标识yy替换为四位yyyy
  • 新格式完全保留对应Locale的日期顺序、分隔符、时间格式规则,仅升级年份为四位,从根源上避免双位年份的跨世纪解析问题

代码示例:

dateField.setFormatterFactory(new JFormattedTextField.AbstractFormatterFactory() {
    @Override
    public JFormattedTextField.AbstractFormatter getFormatter(JFormattedTextField tf) {
        // 此处替换为用户实际选择的Locale即可
        Locale userLocale = Locale.GERMANY;
        DateFormat originalFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, userLocale);
        // 绝大多数场景下Locale返回的DateFormat都是SimpleDateFormat实现
        if (originalFormat instanceof SimpleDateFormat sdf) {
            String rawPattern = sdf.toPattern();
            // 仅替换年份位,其他格式规则完全不变
            String adaptedPattern = rawPattern.replace("yy", "yyyy");
            SimpleDateFormat adaptedFormat = new SimpleDateFormat(adaptedPattern, userLocale);
            // 可选:关闭宽松解析,避免无效日期(如2月30日)被自动修正
            adaptedFormat.setLenient(false);
            return new DateFormatter(adaptedFormat);
        }
        // 极端兼容场景下 fallback 到原生格式
        return new DateFormatter(originalFormat);
    }
});

备选方案:自定义解析逻辑,保留双位年份显示

如果业务要求必须沿用Locale原生的双位年份显示规则,可以自定义DateFormatter重写解析逻辑,完全自主控制年份补全规则,不受默认100年区间限制:

public class FullRangeDateFormatter extends DateFormatter {
    // 可根据业务需求自定义双位年份覆盖范围,示例为以当前年份为基准,前后覆盖1000年
    private static final int YEAR_RANGE_OFFSET = 500;

    public FullRangeDateFormatter(DateFormat format) {
        super(format);
    }

    @Override
    public Object stringToValue(String text) throws ParseException {
        DateFormat format = getFormat();
        Date rawParsed = format.parse(text);
        
        // 提取用户输入的年份
        Pattern yearPattern = Pattern.compile("\\b(\\d{2,4})\\b");
        Matcher matcher = yearPattern.matcher(text);
        if (!matcher.find()) {
            return rawParsed;
        }

        String inputYearStr = matcher.group(1);
        Calendar cal = Calendar.getInstance();
        cal.setTime(rawParsed);
        // 四位年份直接使用用户输入值,不做修正
        if (inputYearStr.length() == 4) {
            cal.set(Calendar.YEAR, Integer.parseInt(inputYearStr));
            return cal.getTime();
        }
        // 双位年份按自定义规则补全世纪
        int inputTwoDigitYear = Integer.parseInt(inputYearStr);
        int currentYear = cal.get(Calendar.YEAR);
        int currentTwoDigitYear = currentYear % 100;
        int centuryBase = currentYear / 100 * 100;
        if (inputTwoDigitYear > currentTwoDigitYear + YEAR_RANGE_OFFSET % 100) {
            centuryBase -= 100 * (YEAR_RANGE_OFFSET / 100 + 1);
        } else if (inputTwoDigitYear < currentTwoDigitYear - YEAR_RANGE_OFFSET % 100) {
            centuryBase += 100 * (YEAR_RANGE_OFFSET / 100 + 1);
        }
        cal.set(Calendar.YEAR, centuryBase + inputTwoDigitYear);
        return cal.getTime();
    }
}

使用时直接用自定义的FullRangeDateFormatter替换原有DateFormatter即可。


内容的提问来源于stack exchange,提问作者Ture Pålsson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:48:04