我们可以看到 LocalTime 和 LocalDateTime 的精度是可以去到 9 也就是达到纳秒
但是为什么我们经常打印出来的时候往往只有小数点后三位、也就是毫秒
我们看到源码最终还是调用了 System的currentTimeMillis
最近测试环境中出现了个时间精度的问题、计算某个流程所花费的时间的时候得出了负数、因为存储该字段的类型设置了无符号、导致插入的时候报错、超出该类型的值的范围。
当时的第一反应是流程对应的步骤是不是分别在不同的容器中执行、容器之间是否存在时间差。
后面排查所有的步骤均执行在同一个容器中、日志打印的时间和sql插入的值均没啥差异。select 出来的值没有打印出来。
后面看到其中日志打印insert 的值的秒比数据库中的秒要少一秒。然后发觉没有设置 dateTime 的精度
这个其实是录入表的同事遗漏了、原本设计表结构是有6位精度的(规范要求)。
后面补上精度、顺手将无符号也去掉
Mysql 中的 dateTime 精度默认为 0 、最大可以去到 6。
如果入参的精度大于 dateTime 的精度、那么将会进行四舍五入。
小结
插入的时候、如果输入的精度比声明的精度高、那么则会对其进行四舍五入
查询
值得注意的是、LocalTime | LocalDateTime 的 MAX 是 9位 的、如果
第二条的查询就最后的参数比第一条的时间多了一个 5
首先看插入结果
那么第一条的查询结果是只有一条
第二条的查询结果却是 3 条。
因为 mysql 将字符串转换成 dateTime 的时候使用的是 6 位的精度、超过六位的才会四舍五入、所以导致第二条的查询条件变为 10-02 00:00:00
我们将 dateTime 的精度改为 2
那么第一条的查询结果为两条
而第二条的查询结果还是为三条
即使将精度改为6也是这样的结果
小结
对于查询而已、mysql 会对 string 的转换如果超出 6 位 多出的会进行四舍五入、然后才会去表中进行比较
事实上对于大多数场景而已、Java 提供的毫秒级别的时间以及能满足大多数场景了、对应到 db 存储时间到精度、
建议直接 6 会比较省心点吧、跟 Mysql 做字符串转换 dateTime 的时候一样。
查询到时候需要注意的是如果上限被包含进去、需要考虑精度是否超过 Mysql 的最大精度、如果超过了则可能你会被舍入
领取专属 10元无门槛券
私享最新 技术干货