使用LocalDateTime处理时间与前端和数据库的无缝对接

一、简介

     通常与前端互相传递时间相关参数,一般为String或Date 类型,而DTO中一般用LocalDateTime处理,这样会发生多次时间格式或类型转换,产生冗余代码。故可以通过全局AOP实现前端所传String类型时间自动映射转化为LocalDateTime类型,后端处理后也自动映射LocalDateTime为String 返回前段。

     其中对于PostgreSQL数据库,不需要额外配置,可以直接在Entity类中定义LocalDateTime类型,通过JPA直接保存或查询时间映射为LocalDateTime类型,对于MySQL可能数据库支持的Date转LocalDateTime需要额外的全局配置,可查阅资料解决。

二、时间转换类的配置



import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;




@Configuration
public class DateConfig {
    /** 默认日期时间格式 */
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /** 默认日期格式 */
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    /** 默认时间格式 */
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    /**
     * LocalDate转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, LocalDate> localDateConverter() {
        return new Converter<String, LocalDate>() {
            @Override
            public LocalDate convert(@NotNull String source) {
                return LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
            }
        };
    }

    /**
     * LocalDateTime转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(@NotNull String source) {
                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT));
            }
        };
    }

    /**
     * LocalTime转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, LocalTime> localTimeConverter() {
        return new Converter<String, LocalTime>() {
            @Override
            public LocalTime convert(@NotNull String source) {
                return LocalTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT));
            }
        };
    }

    /**
     * Date转换器,用于转换RequestParam和PathVariable参数
     */
    @Bean
    public Converter<String, Date> dateConverter() {
        return new Converter<String, Date>() {
            @Override
            public Date convert(@NotNull String source) {
                SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                try {
                    return format.parse(source);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
        };
    }

    /**
     * Json序列化和反序列化转换器,用于转换Post请求体中的json以及将我们的对象序列化为返回响应的json
     */
    @Bean
    public ObjectMapper objectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

        //LocalDateTime系列序列化和反序列化模块,继承自jsr310,我们在这里修改了日期格式
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));


        //Date序列化和反序列化
        javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
            @Override
            public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                String formattedDate = formatter.format(date);
                jsonGenerator.writeString(formattedDate);
            }
        });
        javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
                String date = jsonParser.getText();
                try {
                    return format.parse(date);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }




}

通用时间工具类DateTimeUtil


import org.apache.commons.lang3.StringUtils;

import javax.validation.constraints.NotNull;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;



public class DateTimeUtil {

    private static final String YMDHMS_DATE_FORMAT_T = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
    private static final String ISO8601_DATE_FORMAT_T = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
    private static final String YMDHMS_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final String YMDHMS_DATE_FORMAT_V1 = "yyyy/MM/dd HH:mm:ss";

    private static final String CSV_DATE_FORMAT = "yyyyMMddHHmmss";
    private static final String YMD_DATE_FORMAT = "yyyy-MM-dd";
    private static final String YYYYMMDDHHMMSS_DATE_FORMATE= "yyyyMMddHHmmssSSS";
    /*** 1毫秒 */
    public static final long ONE_MILLI_SECOND = 1l;
    /*** 1秒 */
    public static final long ONE_SECOND = ONE_MILLI_SECOND * 1000;
    /*** 1分钟 */
    public static final long ONE_MINUTE = ONE_SECOND * 60;
    /*** 1小时 */
    public static final long ONE_HOUR = ONE_MINUTE * 60;
    /*** 1天 */
    public static final long ONE_DAY = ONE_HOUR * 24;


    /**
     * 根据日期时间字符串获取日期时间
     * @param datetime
     * @param format 为null或者空时默认为yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static LocalDateTime parseByFormat(@NotNull String datetime,String format) {

        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.parse(datetime,formatter);
    }


    /**
     * 获取指定格式的日期字符串
     * @param dateTime
     * @param format 为null或者空时默认为yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String formatDateTime(@NotNull LocalDateTime dateTime, String format) {
        //时间转字符串格式化
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format, Locale.SIMPLIFIED_CHINESE);
        return dateTime.format(formatter);
    }


    /**
     * LocalDateTime 转为 Date
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime){
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * Date 转 LocalDateTime
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date){
        return LocalDateTime.ofInstant(date.toInstant(),ZoneId.systemDefault());
    }

    /**
     * 根据时间获取时间戳
     * @param dateTime
     * @return
     */
    public static Long dateTimeToTimestamp(LocalDateTime dateTime) {

        if (dateTime == null) {
            return null;
        }
        return dateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }


    /**
     * 根据时间戳获取日期时间
     * @param timestamp
     * @return
     */
    public static LocalDateTime timestampToDateTime(Long timestamp) {
        return timestamp==null?null:LocalDateTime.ofInstant( Instant.ofEpochMilli(timestamp),ZoneId.systemDefault());
    }







    /**
     * 获取当日开始时间0点
     */
    public static LocalDateTime todayStartTime(){
        return LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
    }

    /**
     * 获取当日结束时间0点
     * @return
     */
    public static LocalDateTime todayEndTime(){
        return  LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
    }

    public static void main(String[] args) {
        Date date = new Date();
        String datStr = LocalDateTime.now().toString();



        LocalDateTime localDateTime = DateTimeUtil.dateToLocalDateTime(date);

        Long longSc = DateTimeUtil.dateTimeToTimestamp(localDateTime);

        LocalDateTime localDateTimeStamp = DateTimeUtil.timestampToDateTime(longSc);

        String dateToStr = DateTimeUtil.formatDateTime(localDateTime, YMDHMS_DATE_FORMAT_V1);

        Date date1 = DateTimeUtil.localDateTimeToDate(localDateTime);
        System.out.println("today startTime : " + localDateTimeToDate(DateTimeUtil.todayStartTime()));
        System.out.println("today endTime : " + localDateTimeToDate(DateTimeUtil.todayEndTime()));

        System.out.println(parseByFormat("2018-12-07 09:50:33",null));

        String isoTime = "2019-06-26T19:00:35.823+08:00";

        LocalDateTime localDateTime1 = DateTimeUtil.parseByFormat(isoTime, DateTimeUtil.ISO8601_DATE_FORMAT_T);

        System.out.println("iso Time :" + localDateTime1);

        String isoTime1 = LocalDateTime.now().toString() + "+08:00";
        LocalDateTime localDateTime2 = DateTimeUtil.parseByFormat(isoTime1, DateTimeUtil.ISO8601_DATE_FORMAT_T);
        System.out.println("str iso time : " + isoTime1);

    }


    public static String getGMTTime() {
        Calendar c = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("EEE d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        return sdf.format(c.getTime());
    }


}

三、 测试验证

构造测试数据TimeInfoQuery.java 和 TimeInfoVO.java



import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;

/**
 * @Author: zhenglei12
 * @Data: Created in 2019/7/2 15:15
 * @Description:
 */
@Data
public class TimeInfoQuery {

    private String message;

    @ApiModelProperty(value="时间,格式:yyyy-MM-dd HH:mm:ss", hidden=false, notes="格式:yyyy-MM-dd HH:mm:ss", dataType="String")
    private LocalDateTime startTime;


}

TimeInfoVO.java



import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDateTime;

/**
 * @Author: zhenglei12
 * @Data: Created in 2019/7/2 15:14
 * @Description:
 */
@Data
public class TimeInfoVO {

    private String message;

    @ApiModelProperty(value="时间,格式:yyyy-MM-dd HH:mm:ss", hidden=false, notes="格式:yyyy-MM-dd HH:mm:ss", dataType="String")
    @DateTimeFormat
    private LocalDateTime startTime;
}

 

TimeInfoRepository



import com.hikvision.fsd.ums.core.model.entity.TimeInfoEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

/**
 * @Author: zhenglei12
 * @Data: Created in 2019/7/2 15:43
 * @Description:
 */
@Repository
public interface TimeInfoRepository extends JpaRepository<TimeInfoEntity,String>, JpaSpecificationExecutor<TimeInfoEntity> {

    @Query("select u from TimeInfoEntity u where u.id=:id")
    TimeInfoEntity findById(@Param("id") Integer id);
}

 

controller类测试:



import com.***.fsd.ums.core.model.entity.TimeInfoEntity;
import com.***.fsd.ums.core.model.query.TimeInfoQuery;
import com.***.fsd.ums.core.model.vo.TimeInfoVO;
import com.***.fsd.ums.core.repository.TimeInfoRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * @Author: zhenglei12
 * @Data: Created in 2019/7/2 14:57
 * @Description:
 */
@RestController
@Api(tags = "时间测试")
public class DateController {

    @Autowired
    private TimeInfoRepository timeInfoRepository;
    @Autowired
    private MapperFactory mapperFactory;
    @Autowired
    private MapperFacade mapperFacade;

    @GetMapping("/getDate")
    @ApiOperation(value = "获取时间")
    public LocalDateTime getDate(@RequestParam LocalDate date,
                                 @RequestParam LocalDateTime dateTime,
                                 @RequestParam Date originalDate) {
        System.out.println(date);
        System.out.println(dateTime);
        System.out.println(originalDate);
        return LocalDateTime.now();
    }


    @PostMapping("/postDateInfo")
    @ApiOperation(value = "上传时间信息")
    public TimeInfoVO  saveTimeInfo(@RequestBody TimeInfoQuery query){
        TimeInfoVO vo = new TimeInfoVO();
        vo.setMessage("new Time");
        vo.setStartTime(LocalDateTime.now());

        TimeInfoEntity entity = new TimeInfoEntity();
        entity.setMessage(query.getMessage());
        entity.setStartTime(query.getStartTime());
        timeInfoRepository.save(entity);
        return vo;
    }

    @PostMapping("/getLocalTimeInfoById")
    @ApiOperation(value = "根据id获取时间信息")
    public TimeInfoVO  getLocalTimeInfoById(@RequestParam("id")Integer id){

        TimeInfoVO vo =new TimeInfoVO();

        TimeInfoEntity entity = timeInfoRepository.findById(id);

         vo = mapperFacade.map(entity, TimeInfoVO.class);
        return vo;
    }

}

测试结果:

 

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值