我们的需求是定时在凌晨跑,然后把记录产生的时间置为前一天的最后时间:
比如2022-05-21 00:00:00
执行的,存储为2022-05-20 23:59:59
java代码使用的Calendar
进行的偏移
Calendar preDate = Calendar.getInstance();
preDate.add(Calendar.DATE,-1);
preDate.set(Calendar.HOUR,23);
preDate.set(Calendar.MINUTE,59);
preDate.set(Calendar.SECOND,59);
然后数据库对应的字段为datetime
类型,起初数据库总是偶尔会产生
2022-05-21 00:00:00的数据
经过阅读https://www.jianshu.com/p/e5084b43d07c该大神的文章,恍然大悟,
原来是数据库的
datetime
的毫秒进位导致的,因为我们在使用Calendar
的时候并没有设置毫秒位,所以毫秒是跟随当前时间的。
因为MySQL毫秒部分需要以参数形式传参给数据类型,默认是不保存毫秒的,可以保存1-6位。如果需要保存三位的毫秒值,数据类型可以定义为DATETIME(3)
或TIMESTAMP(3)
,不需要保存毫秒的话,只需要将类型直接写为DATETIME
或TIMESTAMP
这样的话假如代码执行Calendar的时候如果毫秒位>=500,则在存储进MySQL的时候会发生进位,这就是Bug产生的原因。
解决办法:
1> 改代码,设置毫秒位为0或者小于500就行
Calendar preDate = Calendar.getInstance();
preDate.add(Calendar.DATE,-1);
preDate.set(Calendar.HOUR,23);
preDate.set(Calendar.MINUTE,59);
preDate.set(Calendar.SECOND,59);
preDate.set(Calendar.MILLISECOND, 0);
2> 把数据库字段改为datetime(3)
或者把数据库字段改为varchar
存储