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

Spring中@DateTimeFormat(style="M-")的日期格式自定义方案咨询

解决方案:Spring Web多语言日期格式自定义

针对你的需求——在de_DE locale下显示13.01.2000,en_GB locale下显示13/01/2000,同时避免@DateTimeFormat style参数导致的年份位数问题,以下分当前版本(Spring Boot 2.7.x)和升级后版本(Spring Boot 3.x)给出实现方案:


一、Spring Boot 2.7.x(基于java.util.Date)

1. 全局自定义日期格式化器(推荐)

创建一个适配多locale的Formatter,根据当前请求的locale返回对应格式:

import org.springframework.format.Formatter;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class CustomDateFormatter implements Formatter<Date> {
    private final MessageSource messageSource;

    public CustomDateFormatter(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @Override
    public Date parse(String text, Locale locale) throws ParseException {
        SimpleDateFormat sdf = getDateFormat(locale);
        return sdf.parse(text);
    }

    @Override
    public String print(Date object, Locale locale) {
        SimpleDateFormat sdf = getDateFormat(locale);
        return sdf.format(object);
    }

    private SimpleDateFormat getDateFormat(Locale locale) {
        // 从多语言配置文件中读取格式模板
        String pattern = messageSource.getMessage("date.format", null, locale);
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        sdf.setLenient(false); // 严格校验日期格式
        return sdf;
    }
}

注册该格式化器到Spring容器:

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final MessageSource messageSource;

    public WebConfig(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new CustomDateFormatter(messageSource));
    }
}

最后在多语言配置文件中定义格式:

  • messages_de.properties:date.format=dd.MM.yyyy
  • messages_en_GB.properties:date.format=dd/MM/yyyy

2. Controller层局部绑定(按需使用)

如果只需针对特定Controller生效,可使用@InitBinder:

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import java.text.SimpleDateFormat;
import java.util.Locale;

@ControllerAdvice // 全局生效,去掉则仅当前Controller生效
public class DateBindingAdvice {
    @InitBinder
    public void initBinder(WebDataBinder binder, Locale locale) {
        SimpleDateFormat sdf;
        if (Locale.GERMANY.equals(locale)) {
            sdf = new SimpleDateFormat("dd.MM.yyyy");
        } else if (Locale.UK.equals(locale)) {
            sdf = new SimpleDateFormat("dd/MM/yyyy");
        } else {
            sdf = (SimpleDateFormat) SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM, locale);
        }
        sdf.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
    }
}

二、Spring Boot 3.x(推荐使用Java 8+日期API)

Spring Boot 3.x建议迁移到LocalDate等Java 8+日期类,以下是适配方案:

1. 全局自定义LocalDate格式化器

首先修改模型类:

class PersonModel {
   private LocalDate birthdate;
}

创建locale感知的格式化器:

import org.springframework.format.Formatter;
import org.springframework.context.MessageSource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class LocaleAwareLocalDateFormatter implements Formatter<LocalDate> {
    private final MessageSource messageSource;

    public LocaleAwareLocalDateFormatter(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @Override
    public LocalDate parse(String text, Locale locale) {
        DateTimeFormatter formatter = getFormatter(locale);
        return LocalDate.parse(text, formatter);
    }

    @Override
    public String print(LocalDate object, Locale locale) {
        DateTimeFormatter formatter = getFormatter(locale);
        return formatter.format(object);
    }

    private DateTimeFormatter getFormatter(Locale locale) {
        String pattern = messageSource.getMessage("date.format", null, locale);
        return DateTimeFormatter.ofPattern(pattern).withLocale(locale);
    }
}

注册格式化器:

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final MessageSource messageSource;

    public WebConfig(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new LocaleAwareLocalDateFormatter(messageSource));
    }
}

同样在多语言配置文件中定义格式模板即可。


关键注意事项

  • 确保Spring正确识别请求locale:默认通过Accept-Language头解析,可自定义LocaleResolver调整逻辑。
  • 解析日期时设置lenient=false,避免接受无效日期格式。
  • 升级到Spring Boot 3.x时,建议彻底迁移Java 8+日期API,替代老旧的java.util.Date。

内容的提问来源于stack exchange,提问作者Jan Kuenstler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:10:11