springboot日期解析

package xyz.zq.sf.common.core.config;

import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.PackageVersion;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import xyz.zq.sf.common.core.util.LocalDateTimeUtil;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.TimeZone;

/**
 * jackson 配置
 *
 * @author hzq
 * @date 2021-01-27 11:38
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public Jackson2ObjectMapperBuilderCustomizer customizer() {
        return jacksonObjectMapperBuilder -> {
            jacksonObjectMapperBuilder.locale(Locale.CHINA);
            jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
            jacksonObjectMapperBuilder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
            jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance);
            /*
             * 当 Content-type: application/json
             * 对时间类型 序列化及反序列化 格式的转换
             */
            jacksonObjectMapperBuilder.modules(new SfLocalDateTimeModule());
        };
    }

    /**
     * 时间序列化格式转换
     */
    public static class SfLocalDateTimeModule extends SimpleModule {
        public SfLocalDateTimeModule() {
            super(PackageVersion.VERSION);
//            this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
            /*对LocalDateTime类型 使用自定义序列化规则*/
            this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
            this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
            this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
//            this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
            /*对LocalDateTime类型 使用自定义反序列化规则*/
            this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
            this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
            this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
        }
    }

    /**
     * LocalDateTime 序列化 --> 时间戳
     */
    public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers)
                throws IOException {
            if (value != null) {
                long timestamp = value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                gen.writeNumber(timestamp);
            }
        }
    }

    /**
     * LocalDateTime 反序列化
     * 支持格式:
     * yyyy/MM/dd HH:mm:ss
     * yyyy-MM-dd HH:mm:ss
     * yyyyMMddHHmmss
     */
    public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext)
                throws IOException {
            return LocalDateTimeUtil.parseStrToDate(p.getValueAsString(), LocalDateTime.class);
        }
    }


}

package xyz.zq.sf.common.core.config;

import cn.hutool.core.date.DatePattern;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.Parser;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import xyz.zq.sf.common.core.util.LocalDateTimeUtil;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;

import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.SERVLET;

/**
 * Web Mvc配置
 *
 * @author hzq
 * @date 2021-01-27 16:13
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = SERVLET)
public class WebMvcConfiguration implements WebMvcConfigurer {

    /**
     * @param registry 格式器注册表
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        setDateTimeFormatterRegistrar(registry);
    }

    /**
     * 配置日期时间格式注册器
     * 对所有以表单方式提交的日期类型进行转换
     * Content-type:form-data、urlEncode
     *
     * @param registry 格式器注册表
     */
    protected void setDateTimeFormatterRegistrar(FormatterRegistry registry) {
        /*日期时间格式注册器*/
        DateTimeFormatterRegistrar tfr = new DateTimeFormatterRegistrar();
        tfr.setTimeFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
        tfr.setDateFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
        tfr.registerFormatters(registry);
        /*Str To Date解析器*/
        registry.addParser(new StrToDateParser());
        /*Str到本地日期时间解析器*/
        registry.addParser(new StrToLocalDateTimeParser());
    }

    /**
     * String to Date
     * 字符串解析成日期类型
     */
    public static class StrToDateParser implements Parser<Date> {

        @Override
        public Date parse(String text, Locale locale) {
            return LocalDateTimeUtil.parseStrToDate(text, Date.class);
        }
    }

    /**
     * String to LocalDateTime
     * 字符串解析成日期类型
     */
    public static class StrToLocalDateTimeParser implements Parser<LocalDateTime> {

        @Override
        public LocalDateTime parse(String text, Locale locale) {
            return LocalDateTimeUtil.parseStrToDate(text, LocalDateTime.class);
        }
    }
}

package xyz.zq.sf.common.core.util;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import lombok.experimental.UtilityClass;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 当地日期时间工具类
 *
 * @author hzq
 * @date 2021-01-27 13:15
 */
@UtilityClass
public class LocalDateTimeUtil {

    public final static Map<String, Pattern> patternRegexMap = new HashMap<>();
    /*匹配全数字*/
    public final static Pattern timeStampPattern = Pattern.compile("[0-9]*");

    static {
        /*ios 时间格式*/
        patternRegexMap.put("yyyy/MM/dd HH:mm:ss", Pattern.compile("\\d{4}/\\d{1,2}/\\d{1,2}(\\s\\d{1,2}:\\d{1,2}:\\d{1,2})?"));
        /*android 时间格式*/
        patternRegexMap.put("yyyy-MM-dd HH:mm:ss", Pattern.compile("^(\\d{4})-([0-1]\\d)-([0-3]\\d)\\s([0-5]\\d):([0-5]\\d):([0-5]\\d)$"));
        /*时间戳格式*/
        patternRegexMap.put("yyyyMMddHHmmss", Pattern.compile("^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))([0-1]?[0-9]|2[0-3])([0-5][0-9])([0-5][0-9])$"));
    }

    /**
     * 解析
     * String --> Date
     * String --> LocalDateTime
     * 字符串解析成日期类型
     *
     * @param str 字符串类型时间
     * @return Class<T>
     */
    @SuppressWarnings("unchecked")
    public static <T> T parseStrToDate(String str, Class<T> requiredType) {

        if (StrUtil.isBlank(str)) return null;

        /*
         * ios 格式
         * android 格式
         * 时间戳 格式
         */
        for (Map.Entry<String, Pattern> next : LocalDateTimeUtil.patternRegexMap.entrySet()) {
            boolean matches = ReUtil.isMatch(next.getValue(), str);
            if (matches) {
                if (requiredType.isAssignableFrom(Date.class)) {
                    try {
                        return ((T) new SimpleDateFormat(next.getKey()).parse(str));
                    } catch (ParseException ignore) {
                    }
                }
                if (requiredType.isAssignableFrom(LocalDateTime.class)) {
                    return ((T) LocalDateTime.parse(str, DateTimeFormatter.ofPattern(next.getKey())));
                }
            }
        }

        /*
         * 全数字 当成时间戳来解析
         */
        boolean match = ReUtil.isMatch(LocalDateTimeUtil.timeStampPattern, str);
        if (match) {
            if (requiredType.isAssignableFrom(Date.class)) {
                return ((T) new Date(Long.parseLong(str)));
            }
            if (requiredType.isAssignableFrom(LocalDateTime.class)) {
                return ((T) LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(str)), ZoneId.systemDefault()));
            }
        }

        return null;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值