• Mysql DateTime 问题


     /**
     * The maximum supported {@code LocalTime}, '23:59:59.999999999'.
     * This is the time just before midnight at the end of the day.
     */
     public static final LocalTime MAX;
     /**
      * The maximum supported {@code LocalDateTime}, '+999999999-12-31T23:59:59.999999999'.
      * This is the local date-time just before midnight at the end of the maximum date.
      * This combines {@link LocalDate#MAX} and {@link LocalTime#MAX}.
      * This could be used by an application as a "far future" date-time.
      */
     public static final LocalDateTime MAX = LocalDateTime.of(LocalDate.MAX, LocalTime.MAX);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    我们可以看到 LocalTime 和 LocalDateTime 的精度是可以去到 9 也就是达到纳秒

    但是为什么我们经常打印出来的时候往往只有小数点后三位、也就是毫秒

     LocalDateTime now = LocalDateTime.now();
     System.out.println(now);
    
    • 1
    • 2

    我们看到源码最终还是调用了 System的currentTimeMillis

     @Override
     public long millis() {
         return System.currentTimeMillis();
     }
     @Override
     public Instant instant() {
         return Instant.ofEpochMilli(millis());
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    最近测试环境中出现了个时间精度的问题、计算某个流程所花费的时间的时候得出了负数、因为存储该字段的类型设置了无符号、导致插入的时候报错、超出该类型的值的范围。

    当时的第一反应是流程对应的步骤是不是分别在不同的容器中执行、容器之间是否存在时间差。

    后面排查所有的步骤均执行在同一个容器中、日志打印的时间和sql插入的值均没啥差异。select 出来的值没有打印出来。

    后面看到其中日志打印insert 的值的秒比数据库中的秒要少一秒。然后发觉没有设置 dateTime 的精度

    这个其实是录入表的同事遗漏了、原本设计表结构是有6位精度的(规范要求)。

    后面补上精度、顺手将无符号也去掉

    Mysql 中的 dateTime 精度默认为 0 、最大可以去到 6。

    如果入参的精度大于 dateTime 的精度、那么将会进行四舍五入。

    微信公众号:CoderLi

    小结

    插入的时候、如果输入的精度比声明的精度高、那么则会对其进行四舍五入

    查询

    值得注意的是、LocalTime | LocalDateTime 的 MAX 是 9位 的、如果

     drop table mqst1;create table mqst1
     (
         id         int      null,
         createtime datetime(0) null
     );INSERT INTO test_schema.mqst1 (id, createtime) VALUES (1, '2021-10-01 21:08:08.123');
     INSERT INTO test_schema.mqst1 (id, createtime) VALUES (1, '2021-10-01 23:59:59.567');
     INSERT INTO test_schema.mqst1 (id, createtime) VALUES (2, '2021-10-02 00:00:00.000');select *
     from mqst1
     where createtime >= '2021-10-01 00:00:00'  and createtime <= '2021-10-01 23:59:59.999999';select *
     from mqst1
     where createtime >= '2021-10-01 00:00:00' and createtime <= '2021-10-01 23:59:59.9999995';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    第二条的查询就最后的参数比第一条的时间多了一个 5

    首先看插入结果

    微信公众号:CoderLi

    那么第一条的查询结果是只有一条

    第二条的查询结果却是 3 条。

    因为 mysql 将字符串转换成 dateTime 的时候使用的是 6 位的精度、超过六位的才会四舍五入、所以导致第二条的查询条件变为 10-02 00:00:00

    我们将 dateTime 的精度改为 2

     createtime datetime(2) null
    
    • 1

    微信公众号:CoderLi

    那么第一条的查询结果为两条

    而第二条的查询结果还是为三条

    即使将精度改为6也是这样的结果

    小结

    对于查询而已、mysql 会对 string 的转换如果超出 6 位 多出的会进行四舍五入、然后才会去表中进行比较

    事实上对于大多数场景而已、Java 提供的毫秒级别的时间以及能满足大多数场景了、对应到 db 存储时间到精度、

    建议直接 6 会比较省心点吧、跟 Mysql 做字符串转换 dateTime 的时候一样。

    查询到时候需要注意的是如果上限被包含进去、需要考虑精度是否超过 Mysql 的最大精度、如果超过了则可能你会被舍入

     System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).withNano(999999000));
    
    • 1
  • 相关阅读:
    什么是语法糖?Java中有哪些语法糖?
    一种多尺度协同变异的粒子群优化算法(Python代码实现)
    经典算法之直接插入排序(DirectInsert Sort)
    数据挖掘经典十大算法_条件熵、信息增益介绍
    Airtest1.2.7新增断言API介绍
    windows mysql安装卸载,多版本mysql方案
    【计算机毕业设计】11.毕业生信息管理系统+vue
    技术分享 | MySQL Shell 定制化部署 MySQL 实例
    学生HTML个人网页作业作品 (水果商城HTML+CSS)
    Python决策树
  • 原文地址:https://blog.csdn.net/lijinxiong520/article/details/128060327