Skip to content

随记

多尝试后再问人。

springboot时间全局格式化,支持 表单/query/json 传参,支持多种常用时间格式,
入参时间格式可以为yyyy-MM-dd HH:mm:ss,yyyy-MM-dd HH:mmyyyy-MM-dd,yyyy-MM,
返回格式统一为yyyy-MM-dd HH:mm:ss

参考文档

SpringBoot日期格式转换,SpringBoot配置全局日期格式转换器

springboot全局配置,选择了配置这个就不用往下看了

一般如果无特殊需求,可以使用springboot全局时间格式化,前提是入参返参都是yyyy-MM-dd HH:mm:ss格式,
如要需要返回指定格式使用注解@JsonFormat(pattern = "yyyy-MM-dd")传入时间格式即可

yml
spring:
  jackson:
    # 全局json时间格式化
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
  mvc:
    # 表单接收date
    format:
      date: yyyy-MM-dd HH:mm:ss

1. 新建一个springboot工程

这里我用的是

工程目录如下

完整工程gitee地址

gitee

2. 添加json处理时间格式的类

java
package top.zlhy7.config;

import com.fasterxml.jackson.databind.util.StdDateFormat;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author renyong
 * @date 2023/4/15 10:05
 * @description json格式化类
 */
@Component
public class CustomDateFormat extends StdDateFormat {

    private static final long serialVersionUID = -3201781773655300201L;

    @Override
    /**
     * 只要覆盖parse(String)这个方法即可
     */
    public Date parse(String dateStr, ParsePosition pos) {
        return getDate(dateStr, pos);
    }

    @Override
    public Date parse(String dateStr) {
        ParsePosition pos = new ParsePosition(0);
        return getDate(dateStr, pos);
    }

    private Date getDate(String dateStr, ParsePosition pos) {
        SimpleDateFormat sdf = null;
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        } else if (dateStr.matches("^\\d{4}-\\d{1,2}$")) {
            sdf = new SimpleDateFormat("yyyy-MM");
            return sdf.parse(dateStr, pos);
        } else if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
            sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.parse(dateStr, pos);
        } else if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            return sdf.parse(dateStr, pos);
        } else if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.parse(dateStr, pos);
        } else if (dateStr.length() == 23) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            return sdf.parse(dateStr, pos);
        }
        return super.parse(dateStr, pos);
    }

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date, toAppendTo, fieldPosition);
    }

    @Override
    public CustomDateFormat clone() {
        return new CustomDateFormat();
    }
}

3. 添加表单处理时间格式的类

java
package top.zlhy7.config;

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

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author renyong
 * @date 2023/4/15 10:05
 * @description 表单时间转化
 */
@Component
public class DateConverter implements Converter<String, Date> {

    private static final List<String> formarts = new ArrayList<>(4);

    static {
        formarts.add("yyyy-MM");
        formarts.add("yyyy-MM-dd");
        formarts.add("yyyy-MM-dd HH:mm");
        formarts.add("yyyy-MM-dd HH:mm:ss");
    }

    @Override
    public Date convert(String source) {
        String value = source.trim();
        if ("".equals(value)) {
            return null;
        }
        if (source.matches("^\\d{4}-\\d{1,2}$")) {
            return parseDate(source, formarts.get(0));
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
            return parseDate(source, formarts.get(1));
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, formarts.get(2));
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, formarts.get(3));
        } else {
            throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
        }
    }

    /**
     * 格式化日期
     *
     * @param dateStr String 字符型日期
     * @param format  String 格式
     * @return Date 日期
     */
    private Date parseDate(String dateStr, String format) {
        Date date = null;
        try {
            DateFormat dateFormat = new SimpleDateFormat(format);
            date = dateFormat.parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }
}

4. 添加时间格式处理配置类

java
package top.zlhy7.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author renyong
 * @date 2023/4/15 10:06
 * @description 全局时间处理
 * 参考文档 https://striveday.blog.csdn.net/article/details/110632544
 */
@Configuration
public class GlobalTimeFormatConfig{
    /**
     * JSON全局日期转换器
     */
    @Bean
    public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter(CustomDateFormat customDateFormat) {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        //设置日期格式
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setDateFormat(customDateFormat);
        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
        //设置中文编码格式
        List<MediaType> list = new ArrayList<MediaType>(1);
        list.add(MediaType.APPLICATION_JSON_UTF8);
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
        return mappingJackson2HttpMessageConverter;
    }

    /**
     * 表单全局日期转换器
     */
    @Bean
    public ConversionService getConversionService(DateConverter dateConverter) {
        ConversionServiceFactoryBean factoryBean = new ConversionServiceFactoryBean();
        Set<Converter> converters = new HashSet<>();
        converters.add(dateConverter);
        factoryBean.setConverters(converters);
        return factoryBean.getObject();
    }
}

5. 测试控制器

java
package top.zlhy7.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.zlhy7.DemoVo;

import java.util.Date;

/**
 * @author renyong
 * @date 2023/4/15 00:01
 * @description 测试控制器
 */
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
    /**
     * 单独date属性并返回单属性,query传参
     */
    @GetMapping("/test1")
    public Date test1(Date date1){
        log.info("单独date属性并返回单属性,query传参,{}",date1);
        return date1;
    }
    /**
     * 对象包含date属性并返回对象,query传参
     */
    @GetMapping("test2")
    public DemoVo test2(DemoVo demoVo){
        log.info("对象包含date属性并返回对象,query传参,{}",demoVo);
        return demoVo;
    }
    /**
     * 对象包含date属性并返回对象,body传参
     */
    @PostMapping("test3")
    public DemoVo test3(@RequestBody DemoVo demoVo){
        log.info("对象包含date属性并返回对象,body传参,{}",demoVo);
        return demoVo;
    }
}

DemoVo.java

java
package top.zlhy7;

import lombok.Data;
import java.util.Date;

/**
 * @author renyong
 * @date 2023/4/15 10:02
 * @description
 */
@Data
public class DemoVo {
    /**
     * 年龄
     */
    private int age;
    /**
     * 生日
     */
    private Date birthday;
}

6. 验证配置

6.1 单参数接收date

  • yyyy-MM-dd HH:mm:ss
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04-15%2010:44:25' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'
  • yyyy-MM-dd HH:mm
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04-15%2010:44' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'
  • yyyy-MM-dd
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04-15' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'
  • yyyy-MM
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'

6.2 对象属性数接收date,或者表单接收

  • yyyy-MM-dd HH:mm:ss
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04-15%2010:44:25' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'
  • yyyy-MM-dd HH:mm
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04-15%2010:44' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'
  • yyyy-MM-dd
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04-15' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'
  • yyyy-MM
shell
curl --location --request GET 'http://127.0.0.1:8080/test/test1?date1=2023-04' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive'

6.3 json接收date属性

  • yyyy-MM-dd HH:mm:ss
shell
curl --location --request POST 'http://127.0.0.1:8080/test/test3' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive' \
--data '{
    "age": 0,
    "birthday": "2023-04-15 11:23:23"
}'
  • yyyy-MM-dd HH:mm
shell
curl --location --request POST 'http://127.0.0.1:8080/test/test3' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive' \
--data '{
    "age": 0,
    "birthday": "2023-04-15 11:23"
}'
  • yyyy-MM-dd
shell
curl --location --request POST 'http://127.0.0.1:8080/test/test3' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive' \
--data '{
    "age": 0,
    "birthday": "2023-04-15"
}'
  • yyyy-MM
shell
curl --location --request POST 'http://127.0.0.1:8080/test/test3' \
--header 'User-Agent: Apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Host: 127.0.0.1:8080' \
--header 'Connection: keep-alive' \
--data '{
    "age": 0,
    "birthday": "2023-04"
}'

Released under the MIT License.