You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中日期比较返回-1异常:同日期比较也得-1的问题排查

问题分析与修复方案

看起来你遇到了java.sql.Date比较的经典时间戳坑,我来帮你拆解问题根源和解决办法:

为什么同日期比较会返回-1?

核心问题出在你创建currentDate的方式,以及java.sql.Date和java.util.Date的隐性差异:

  1. 时间戳的本质区别:
    java.sql.Date是专门用于存储纯年月日的类型,它的时间戳会自动把时分秒、毫秒全部清零(比如2020-04-10对应的是当天00:00:00的毫秒数)。
    而你代码里的new Date(new java.util.Date().getTime()),如果没有明确指定全类名,这里的Date大概率是java.util.Date——这个类型会包含当前完整的时间(比如2020-04-10 15:42:30的毫秒数)。

  2. compareTo的底层逻辑:
    当你用数据库返回的java.sql.Date(0点时间戳)和currentDate(当天下午的时间戳)调用compareTo时,本质是比较两个时间戳的大小:0点的毫秒数必然小于当天下午的毫秒数,所以哪怕日期是同一天,也会返回-1,完全符合时间戳的比较逻辑。

另外你代码里还有个小细节:System.err.println("CAST= " +(Date) date);这里的强制转换如果是转成java.util.Date,虽然语法没问题,但会进一步加深类型混淆,没必要这么做。

修复方案

方案1:确保currentDate是纯年月日的java.sql.Date

把currentDate的创建改成明确的java.sql.Date,内部会自动清零时分秒:

// 直接用当前时间戳创建java.sql.Date,自动置零时分秒
java.sql.Date currentDate = new java.sql.Date(System.currentTimeMillis());

如果需要更精准的时区控制,可以用Calendar手动清零时间部分:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
java.sql.Date currentDate = new java.sql.Date(cal.getTimeInMillis());

这样currentDate和数据库返回的java.sql.Date格式完全一致,同日期比较就会返回0了。

方案2:用Java 8+的LocalDate替代(推荐)

如果你的项目是Java 8及以上,强烈建议用java.time.LocalDate来处理纯日期逻辑,它天生只关注年月日,没有时间部分的坑,语义也更清晰:

try { 
    String hql = "SELECT taskDate FROM TaskFutureDates t WHERE t.taskId= :taskId"; 
    // Hibernate 5.2+支持直接将查询结果映射为LocalDate
    List<LocalDate> result = em.createQuery(hql, LocalDate.class)
                               .setParameter("taskId", taskId)
                               .getResultList(); 
    LocalDate currentDate = LocalDate.now(); 
    if (!result.isEmpty()) { 
        for(LocalDate date: result) { 
            // 用isEqual和isAfter替代compareTo,语义更直观
            if(date.isEqual(currentDate) || date.isAfter(currentDate)) { 
                System.err.println("DATE= " + date); 
                return Date.valueOf(date); // 如需返回java.sql.Date,直接转换即可
            } 
        } 
    } 
} catch (Exception e) { 
    e.printStackTrace(); // 建议不要注释掉异常打印,方便排查问题
} 
return null; 

额外小建议

  • 检查代码的导入语句,避免java.util.Date和java.sql.Date的混淆,必要时用全类名指定
  • 代码里的: taskId有个多余的空格,虽然HQL可能兼容,但写成:taskId更规范
  • 不要忽略异常处理,打印异常栈信息能帮你快速定位后续的潜在问题

内容的提问来源于stack exchange,提问作者sagar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 10:17:38