Java代码获取当天最晚时间写入数据库自动变为下一天的00:00:00

背景

有个需求要求将用户上传的年/月/日格式时间转为当天最晚时间23:59:59,例如上传2023/10/15,转换为2023/10/15 23:59:59,并将其存入数据库,数据库字段类型为datetime。
部分代码如下:

public static Date getEndOfDay(Date date) {
    LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
    LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
    return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
}

先将字符串"2023/10/15"格式的时间转为Date类型,再获取当天23:59:59。
测试时,发现数据库中数据一直显示为第二天的00:00:00,比如上述示例,显示为2023-10-16 00:00:00。

原因

在MySQL 5.6.4版本后,新增Fractional Seconds特性,参考MySQL使用手册11.2.8 Conversion Between Date and Time Types,在时间格式转换时,毫秒数在低于500时舍弃,大于等于500进位。

而在上述代码,Date精确到时分秒,看不到毫秒数,打印毫秒数可以看到

public static void main(String[] args) {
        Date now = new Date();
        Date endOfDay = getEndOfDay(now);
        System.out.println(endOfDay.getTime());
    }

Java代码获取当天最晚时间写入数据库自动变为下一天的00:00:00_第1张图片
代码获取的当天最晚时间毫秒位为999,而2023-10-15 23:59:59 对应毫秒数是1697385599000,所以落库会自动进位。

方案

若想生成的时间落库不自动进位,可以将获取的时间向前偏移,这个case偏移999,.minusMillis(999)
可以选择偏移500-999,使最终毫秒位小于500就行。
如下代码:

public static Date getEndOfDay(Date date) {
    LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
    LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
    return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant().minusMillis(999));
}

你可能感兴趣的:(小白启程,java,数据库)