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

表单datetime-local值如何适配Spring指定格式的Date类型?

问题描述

表单使用如下datetime-local输入框:

<input type="datetime-local" id="enddate" name="endDate" class="form-control" placeholder="endDate">

Spring实体类字段定义:

@DateTimeFormat(pattern = "dd.MM.yyyy hh:mm:ss")
private Date endDate;

提交表单后出现类型转换错误,完整错误信息翻译如下:

2022-10-17 12:34:20.614 WARN 12128 --- [nio-8081-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : 已解析 [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1个错误
对象'threads'的字段'endDate'存在字段错误: 被拒绝的值 [2022-10-28T12:34];
错误码 [typeMismatch.threads.endDate,typeMismatch.endDate,typeMismatch.java.time.LocalDateTime,typeMismatch]; 参数 [org.springframework.context.support.DefaultMessageSourceResolvable: 错误码 [threads.endDate,endDate]; 参数 []; 默认消息 [endDate]]; 默认消息 [无法将属性'endDate'的类型'java.lang.String'转换为所需类型'java.time.LocalDateTime'; 嵌套异常为org.springframework.core.convert.ConversionFailedException: 无法将值'2022-10-28T12:34'从类型[java.lang.String]转换为类型[@org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime]; 嵌套异常为java.lang.IllegalArgumentException: 解析值[2022-10-28T12:34]失败]]

要求必须保留@DateTimeFormat注解和Date类型,需解决表单输入值到Date类型的映射问题。


解决方案

方法1:给特定字段注册自定义属性编辑器

通过全局Controller增强类,专门为endDate字段注册属性编辑器,直接解析前端传入的yyyy-MM-ddTHH:mm格式字符串为Date对象,原注解可保留用于输出时的格式化。

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@ControllerAdvice
public class GlobalBindingInitializer {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, "endDate", new PropertyEditorSupport() {
            private final SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");

            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                if (text == null || text.isEmpty()) {
                    setValue(null);
                    return;
                }
                try {
                    Date parsedDate = inputFormat.parse(text);
                    setValue(parsedDate);
                } catch (ParseException e) {
                    throw new IllegalArgumentException("日期格式无效,需符合yyyy-MM-dd'T'HH:mm格式", e);
                }
            }
        });
    }
}

方法2:全局注册String转Date转换器

实现Spring的Converter接口,全局处理所有String到Date的转换,前端传入的yyyy-MM-ddTHH:mm格式字符串会被自动解析为Date对象,原@DateTimeFormat注解仍负责输出格式化。

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class StringToDateConverter implements Converter<String, Date> {

    private final SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");

    @Override
    public Date convert(String source) {
        if (source == null || source.isEmpty()) {
            return null;
        }
        try {
            return inputFormat.parse(source);
        } catch (ParseException e) {
            throw new IllegalArgumentException("无效的日期格式: " + source, e);
        }
    }
}

方法3:前端提交前转换格式(不推荐)

若允许修改前端代码,可在表单提交前将datetime-local的值转换为dd.MM.yyyy hh:mm:ss格式,但需处理24小时转12小时的逻辑,较为繁琐:

document.querySelector('form').addEventListener('submit', function(e) {
    const endDateInput = document.getElementById('enddate');
    if (endDateInput.value) {
        const [datePart, timePart] = endDateInput.value.split('T');
        const [year, month, day] = datePart.split('-');
        const [hour, minute] = timePart.split(':');
        // 转换为12小时制
        let formattedHour = parseInt(hour) % 12;
        formattedHour = formattedHour === 0 ? 12 : formattedHour;
        endDateInput.value = `${day}.${month}.${year} ${formattedHour}:${minute}:00`;
    }
});

注意事项

  • 若使用Spring Boot 2.x及以上版本,@DateTimeFormat默认适配Java 8日期API,但你坚持使用java.util.Date,上述两种后端方案是最稳妥的选择。
  • 方法1仅针对endDate字段生效,方法2全局处理所有String到Date的转换,可根据实际需求选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:25:41