【Hutool】DateUtil.endOfHour、DateUtil.endOfDay得到的时间保存到MySQL时会增加一秒
【Hutool】DateUtil.endOfHour、DateUtil.endOfDay得到的时间保存到MySQL时会增加一秒
目录
一、问题分析
冷知识:
MySQL
数据库对于毫秒大于500
的数据进行进位,所以就造成了MySQL
中的时间多一秒。
.
一般数据库表的字段类型 datetime
/timestamp
长度都是设置为 0
。
二、测试代码
- 获取某小时的结束时间
CalendarUtil.ceiling(date.toCalendar(), DateField.HOUR_OF_DAY, true)
:
public static void main(String[] args) {
DateTime date = DateUtil.parse("2025-04-08 14:00:00.499");
// date = 2025-04-08 14:00:00
System.out.println("date = " + date);
// date.millisecond() = 499
System.out.println("date.millisecond() = " + date.millisecond());
// endOfHour.millisecond() = 999
DateTime endOfHour = DateUtil.endOfHour(date);
System.out.println("endOfHour.millisecond() = " + endOfHour.millisecond());
// 核心代码:
Calendar calendar = CalendarUtil.ceiling(date.toCalendar(), DateField.HOUR_OF_DAY, true);
DateTime dateTime = new DateTime(calendar);
// dateTime = 2025-04-08 14:59:59
System.out.println("dateTime = " + dateTime);
// dateTime.millisecond() = 0
System.out.println("dateTime.millisecond() = " + dateTime.millisecond());
}
- 获取某天的结束时间
CalendarUtil.ceiling(date.toCalendar(), DateField.DAY_OF_MONTH, true)
:
public static void main(String[] args) {
DateTime date = DateUtil.parse("2025-04-08 14:00:00.499");
// date = 2025-04-08 14:00:00
System.out.println("date = " + date);
// date.millisecond() = 499
System.out.println("date.millisecond() = " + date.millisecond());
// endOfDay.millisecond() = 999
DateTime endOfDay = DateUtil.endOfDay(date);
System.out.println("endOfDay.millisecond() = " + endOfDay.millisecond());
// 核心代码:
Calendar calendar = CalendarUtil.ceiling(date.toCalendar(), DateField.DAY_OF_MONTH, true);
// System.out.println("calendar.getTime() = " + calendar.getTime());
DateTime dateTime = new DateTime(calendar);
// dateTime = 2025-04-08 23:59:59
System.out.println("dateTime = " + dateTime);
// dateTime.millisecond() = 0
System.out.println("dateTime.millisecond() = " + dateTime.millisecond());
}
⭐三、解决方案⭐
将
truncateMillisecond
设置成true
即可截断毫秒值(将毫秒数设为0),避免 MySQL的进位问题。
🔨 获取某小时的结束时间 DateUtil.endOfHour(date)
替换代码:
Calendar calendar = CalendarUtil.ceiling(date.toCalendar(), DateField.HOUR_OF_DAY, true);
DateTime dateTime = new DateTime(calendar);
🔧 获取某天的结束时间 DateUtil.endOfDay(date)
替换代码:
Calendar calendar = CalendarUtil.ceiling(date.toCalendar(), DateField.DAY_OF_MONTH, true);
DateTime dateTime = new DateTime(calendar);
四、追根溯源
🔎 cn.hutool.core.date.DateModifier
类下,将 truncateMillisecond
设置成 true
即可截断毫秒值(将毫秒数设为0),避免 MySQL的进位问题。
/**
* ......
* @param truncateMillisecond 是否归零毫秒
* @return 修改后的{@link Calendar}
* @since 5.7.5
*/
public static Calendar modify(Calendar calendar, int dateField, ModifyType modifyType, boolean truncateMillisecond) {
// ......
final int endField = truncateMillisecond ? Calendar.SECOND : Calendar.MILLISECOND;
// ......
if (truncateMillisecond) {
// 将毫秒数设为0(将时间中的毫秒数去除,只保留到秒)
calendar.set(Calendar.MILLISECOND, 0);
}
return calendar;
}
DateUtil.endOfHour(date)
、DateUtil.endOfDay(date)
默认 truncateMillisecond
都为 false
。
以下只举例 DateUtil.endOfDay(date)
源码,其它 DateUtil.endOfXxx
类似:
.
五、参考文章
- 【CSDN】Java--new Date插入mysql数据库,数据库时间多一秒问题.
- 【CSDN】MySQL数据库对于毫秒大于500的数据会进位.
- 【CSDN】JDBC - new Date插入mysql数据库,数据库时间多一秒问题.
- 【CSDN】hutool的bug之 DateUtil.endOfDay(DateUtil.date()).
六、彩蛋
🔨 :hammer:
:hammer:
🔧 :wrench:
:wrench: