zoukankan      html  css  js  c++  java
  • 开发中时间变换问题汇总

    各个时间类型概念及转换

    1. 数据库中的时间类型

    1.1 DATE类型

    DATE只表示日期,检索以YYYY-MM-DD的格式显示,范围是1000-01-01到9999-12-31。因为没有时分秒,所以会损失时间精度。

    1.2 DATETIME类型

    DATETIME表示了日期和时间,检索以YYYY-MM-DD HH:MM:SS格式显示。

    时间范围是 “1000-00-00 00:00:00” 到 “9999-12-31 23:59:59”。

    1.3 TIME类型

    TIME只表示时间,检索以HH:MM:SS格式显示,范围是00:00:00到23:59:59

    1.4 TIMESTAMP类型

    TIMESTAMP似于linux系统 中的unix timestamp,是一个记录了从格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒(北京时间 1970 年 01 月 01 日 08 时 00 分 00 秒)起至现在的总秒数

    此外还可以精确到毫秒微秒,timestamp(3)指毫秒,timestamp(6)微秒。

    支持的时间范围是 “1970-01-01 00:00:01” 到 “2038-01-19 03:14:07”。

    TIMESTAMPDATETIME表示格式一样两者的不同点如下

    • 当使用TIMESTAMP的时候,数据有更新的时候这个字段自动更新为当前时间,所以可以作为lastmodify使用,这个变化是默认设置,如果想使时间不更新可以设置DEFAULT CURRENT_TIMESTAMP
    • TIMESTAMP的范围不能早于1970或者晚于2037,超过这个时间范围的话为0
    • TIMESTAMP存储的时候是转为UTC存储的,获取的时候根据客户端所在时区进行展示
    • timestamp占4个字节datetime占8个字节

    2. Java中的时间类型

    2.1 yyyy-MM-dd HH:mm:ss代表的意义

    字符 意义 时间
    yyyy 2018
    MM`` 01
    dd 16
    hh 12小时制 03
    HH 24小时制 15
    mm 59
    ss 59
    SSS 毫米 333

    2.2 java.util.Date类

    Javajava.util.Date类是Java最初的时间类之一。今天该类的大部分方法已不推荐使用,取而代之的是java.util.Calendar类。

    @Test
    public void testDateTime(){
        Date date = new Date();
        date;            //  默认使用当前的系统时间:Tue Oct 06 18:56:37 CST 2020
        date.getTime();  //  获取当前对象距离1970年1月1日0时0分0秒的毫秒数:1601981797012
        SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");  // 用来格式化时间
        SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        dateFormat1.format(date); // 返回的是字符串格式:2020-10-06
        dateFormat2.format(date); // 返回的是字符串格式:2020-10-06 18:56:37
    }
    

    2.2 java.sql中的时间类型

    java.sql包中有三种时间类型:

    Date:表示日期。如:2018-08-26,只有年月日。

    Time:表示时间。如:11:52:08,只有时分秒。

    Timestamp:表示时间戳。如:2018-08-26 11:52:08.896,有年月日时分秒,以及毫秒。

    这三种时间类型都是继承于java.util.Date类,所以sql中的时间类型是对父类的引用,不需要进行转换

    public class Date extends java.util.Date{}
    public class Time extends java.util.Date {}
    public class Timestamp extends java.util.Date {}
    

    java.sql包下的Date、Time、TimeStamp三个类的构造器都需要一个long类型的参数,表示毫秒值。

    java.util.Date d = new java.util.Date();
    //时间的long型数据
    long longtime = d.getTime();
    
    //Date日期: 2020-10-06
    java.sql.Date date = new java.sql.Date(longtime);
    
    //Time时间: 19:06:45
    java.sql.Time time = new java.sql.Time(longtime);
    
    //Timestamp时间戳,有年月日时分秒,以及毫秒 : 2020-10-06 19:06:45.603
    java.sql.Timestamp timestamp = new java.sql.Timestamp(longtime);
    

    2.3 java.time

    Java的 Date,Calendar类型与前端和数据库交互起来较为麻烦,而且Date类线程不安全等诸多弊端。

    在Java8时推出了线程安全、简易、高可靠的time包。并且数据库中也支持LocalDateTime类型,在数据存储时候使时间变得简单。

    time包中有三个重要的时间类型:年月日时分秒毫秒类型LocalDateTime、年月日类型LocalDate、时分秒毫秒类型LocalTime和数据库中的时间类型一致。

    简单使用

    1. 获取当前时间
    LocalDate.now();    	// 2020-10-06
    LocalTime.now();    	// 19:13:49.696 时分秒毫秒
    LocalDateTime.now();    // 2020-10-06T19:13:49.696
    
    1. 时间格式化:使用DateTimeFormatter是线程安全的,而SimpleDateFormat是线程不安全的。
    // 2020-10-06T19:21:39.254
    LocalDateTime now = LocalDateTime.now();
    
    // 年月日: 2020-10-06
    String format = now.format(DateTimeFormatter.ISO_LOCAL_DATE);   
    
    // 时分秒毫秒 : 2020-10-06
    String format1 = now.format(DateTimeFormatter.ISO_TIME);        
    
    // 2020-10-06 19:21:39
    String format2 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));   
    

    2.4 Date与LocalDateTime转换

    参考:https://www.cnblogs.com/huanshilang/p/12013386.html

    /**
      * LocalDateTime转毫秒时间戳
      * @param localDateTime LocalDateTime
      * @return 时间戳
      */
    public static Long localDateTimeToTimestamp(LocalDateTime localDateTime) {
        try {
            ZoneId zoneId = ZoneId.systemDefault();
            Instant instant = localDateTime.atZone(zoneId).toInstant();
            return instant.toEpochMilli();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 时间戳转LocalDateTime
     * @param timestamp 时间戳
     * @return LocalDateTime
     */
    public static LocalDateTime timestampToLocalDateTime(long timestamp) {
        try {
            Instant instant = Instant.ofEpochMilli(timestamp);
            ZoneId zone = ZoneId.systemDefault();
            return LocalDateTime.ofInstant(instant, zone);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * Date转LocalDateTime
     * @param date Date
     * @return LocalDateTime
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        try {
            Instant instant = date.toInstant();
            ZoneId zoneId = ZoneId.systemDefault();
            return instant.atZone(zoneId).toLocalDateTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * LocalDateTime转Date
     * @param localDateTime LocalDateTime
     * @return Date
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        try {
            ZoneId zoneId = ZoneId.systemDefault();
            ZonedDateTime zdt = localDateTime.atZone(zoneId);
            return Date.from(zdt.toInstant());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    

    2.5 Springboot中使用LocalDateTime

    方式一:

    LocalDateTime字段以时间戳的方式返回给前端 添加日期转化类

    public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime value, 
                              JsonGenerator gen, 
                              SerializerProvider serializers) throws IOException {
            gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli());
        }
    }
    

    并在LocalDateTime字段上添加@JsonSerialize(using = LocalDateTimeConverter.class)注解,如下:

    @JsonSerialize(using = LocalDateTimeConverter.class)
    protected LocalDateTime createdTime;
    

    方式二:

    LocalDateTime字段指定格式化日期的方式返回给前端 在LocalDateTime字段上添加

    @JsonFormat(shape = JsonFormat.Shape.STRING, 
                pattern = "yyyy-MM-dd HH:mm:ss", 
                timezone = "GMT+8")
    protected LocalDateTime createdTime;
    

    前端传入的日期进行格式化LocalDateTime字段上添加

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    protected LocalDateTime gmtModified;
    

    2.6 MybatisPlus操作时间数据类型

    假如数据库中的时间类型为datetime,那么使用高版本MybatisPlus生成器生成的实体类的时间类型为LocalDateTime

    例如:

    // 数据库中的时间类型
    `created_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '文件创建时间',
    
    // java中的时间类型
    private LocalDateTime createdTime;
    

    BUG:当使用MP操作数据库进行数据查询时,如果druid数据库连接池的版本低于1.1.18将会因为时间格式不匹配而报错

    Error attempting to get column 'create_time' from result set. 
    Cause: java.sql.SQLFeatureNotSupported
    

    解决:druid数据库连接池升级到1.1.18版本以上即可正常操作,不需要转换实体类中的时间类型为Date

  • 相关阅读:
    linux文件锁flock【转】
    无尽的悲伤
    go的临时对象池--sync.Pool
    golang 小知识-持续更新中
    【转】Go Channels
    Golang文件名命名规则
    Parquet存储格式
    预装的Office2016,文件图标表显示以及新建失败问题解决 方法
    Gamma编码及Delta编码概述
    java web开发环境配置系列(二)安装tomcat
  • 原文地址:https://www.cnblogs.com/code-duck/p/13775491.html
Copyright © 2011-2022 走看看