/**
* 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);
咱们可以看到 LocalTime 和 LocalDateTime 的精度是可以去到 9 也就是到达纳秒
可是为什么咱们常常打印出来的时分往往只有小数点后三位、也就是毫秒
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
咱们看到源码最终仍是调用了 System的currentTimeMillis
@Override
public long millis() {
return System.currentTimeMillis();
}
@Override
public Instant instant() {
return Instant.ofEpochMilli(millis());
}
最近测试环境中呈现了个时刻精度的问题、计算某个流程所花费的时刻的时分得出了负数、因为存储该字段的类型设置了无符号、导致插入的时分报错、超出该类型的值的规模。
当时的榜首反应是流程对应的过程是不是分别在不同的容器中履行、容器之间是否存在时刻差。
后边排查所有的过程均履行在同一个容器中、日志打印的时刻和sql插入的值均没啥差异。select 出来的值没有打印出来。
后边看到其中日志打印insert 的值的秒比数据库中的秒要少一秒。然后发觉没有设置 dateTime 的精度
这个其实是录入表的同事遗漏了、本来设计表结构是有6位精度的(规范要求)。
后边补上精度、随手将无符号也去掉
Mysql 中的 dateTime 精度默以为 0 、最大可以去到 6。
假如入参的精度大于 dateTime 的精度、那么将会进行四舍五入。
小结
插入的时分、假如输入的精度比声明的精度高、那么则会对其进行四舍五入
查询
值得留意的是、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';
第二条的查询就最后的参数比榜首条的时刻多了一个 5
首先看插入成果
那么榜首条的查询成果是只有一条
第二条的查询成果却是 3 条。
因为 mysql 将字符串转化成 dateTime 的时分使用的是 6 位的精度、超越六位的才会四舍五入、所以导致第二条的查询条件变为 10-02 00:00:00
咱们将 dateTime 的精度改为 2
createtime datetime(2) null
那么榜首条的查询成果为两条
而第二条的查询成果仍是为三条
即便将精度改为6也是这样的成果
小结
关于查询罢了、mysql 会对 string 的转化假如超出 6 位 多出的会进行四舍五入、然后才会去表中进行比较
事实上关于大多数场景罢了、Java 提供的毫秒级别的时刻以及能满足大多数场景了、对应到 db 存储时刻到精度、
主张直接 6 会比较省心点吧、跟 Mysql 做字符串转化 dateTime 的时分一样。
查询到时分需求留意的是假如上限被包含进去、需求考虑精度是否超越 Mysql 的最大精度、假如超越了则可能你会被舍入
System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).withNano(999999000));
本文由mdnice多渠道发布