【问题标题】:JDBC java.sql.Date() comparison is giving falseJDBC java.sql.Date() 比较给出错误
【发布时间】:2014-09-07 13:13:51
【问题描述】:

我很好奇为什么 if 比较给出错误:

我正在使用此代码将日期插入日期字段:

preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));
System.out.println("sql date" + new java.sql.Date(new java.util.Date().getTime()));
output is: 2014-07-16

插入后我查询数据库以确定今天是否插入了记录:

    String sql = select MAX (last_modified) as last_modified from mydb.mytable
    ResultSet rs = stmt.executeQuery(sql);

    while (rs.next())
    {

        if (rs.getDate(1).equals(new java.sql.Date(new java.util.Date().getTime())))
        {
            System.out.println("Same Date in here not need to update");
         }
        else
        {
            System.out.println("Dates are different");
        }

        System.out.println("date from db: " + rs.getDate(1));  
        System.out.println("new sql date: " + new java.sql.Date(new java.util.Date().getTime()));: 
    }

输出是:

Dates are different
date from db: 2014-07-16
new sql date: 2014-07-16

我认为这两个日期相似,并且都在转换以匹配 java.sql.Date,也许条件不正确。

感谢您对理解此行为的任何帮助。

【问题讨论】:

    标签: java sql sql-server date jdbc


    【解决方案1】:

    您正在比较 Datelong

    if (rs.getDate(1).equals(new java.sql.Date(new java.util.Date().getTime())))
    

    改成

    if (rs.getDate(1).getTime() == System.currentTimeInMillis())
    

    根据您的评论,您需要日级精度,所以

        Calendar startOfToday = Calendar.getInstance();
        Calendar endOfToday = Calendar.getInstance();
        endOfToday.setTime(startOfToday.getTime());
    
        startOfToday.set(Calendar.HOUR_OF_DAY, 0);
        startOfToday.set(Calendar.MINUTE, 0);
        startOfToday.set(Calendar.SECOND, 0);
        startOfToday.set(Calendar.MILLISECOND, 0);
    
        endOfToday.set(Calendar.HOUR_OF_DAY, 23);
        endOfToday.set(Calendar.MINUTE, 59);
        endOfToday.set(Calendar.SECOND, 59);
        endOfToday.set(Calendar.MILLISECOND, 999);
    
        long transactionDate = rc.getDate(1).getTime();
        if(transactionDate >= startOfToday.getTimeInMillis() && transactionDate <= endOfToday.getTimeInMillis()){
    
        }
    

    【讨论】:

    • 如果我这样做,我会得到:无法在原始类型 long 上调用 equals(Date)
    • 已修复,但此比较将日期与您的代码中的毫秒精度进行比较,看起来您需要这样做
    • 这给了我这个输出: rs gettime: 1405486800000 rs system millisec: 1405544365833 结果仍然是“日期不同”我想知道交易是否发生在同一日期 2014-07 -16
    • 哇!出色的答案!完全有效。非常感谢!
    【解决方案2】:

    将您的测试更改为:

    if (rs.getDate(1).toString().equals(new java.sql.Date(System.currentMillis()).toString())
    

    【讨论】:

    • 这里的情况相同,因为自从插入比较以来发生了一段时间,我给出了这个输出:rs gettime: 1405486800000 rs system miisecs: 1405544807311 Dates are different date from db: 2014-07-16新sql日期2014-07-16
    • 试试这个改变(我没有方便的 IDE 来测试这个,但它可以工作,因为 SQL 日期忽略了时间部分)
    • 它确实有效!语句:System.out.println(new java.sql.Date(System.currentTimeMillis()).toString());输出:2014-07-22
    • @Israelm 确切地说:java.sql.Date 是正常的,除了它忽略其 toString() impl 中的小时、分钟和秒。
    【解决方案3】:

    你工作太辛苦了。在现代 Java 中有更简单、更清晰的方法来进行此类比较。

    旧的 java.util.Date、java.sql.Date 和 .Calendar 类是出了名的麻烦,应该避免使用。

    java.sql.Date 是一个黑客

    java.sql.Date 只是一个 java.util.Date,其时间设置为 00:00:00 (UTC)。这是一个古老的蹩脚技巧,可以绕过 Java 的早期版本缺少一个类来表示没有任何时间或时区的仅日期的事实。

    java.time

    现在 Java 8 确实有一个仅日期类 LocalDate,在新的 java.time package 中找到。

    已将方法添加到 java.sql.Date 类以转换为 LocalDate 或从 LocalDate 转换。

    LocalDate localDate = someSqlDate.toLocalDate();
    LocalDate today = LocalDate.now( ZoneOffset.UTC ); // Pass a time zone to get current date in UTC for fair comparison.
    boolean localDateIsToday = localDate.isEqual( today );
    

    走另一条路……

    java.sql.Date sqlDate = java.sql.Date.valueOf( someLocalDate );
    

    JDBC 4.2 驱动程序

    如果你的JDBC driver已经更新支持JDBC 4.2,那么根据JDBC 4.2 Spec Update(项目#21)你可以在ResultSet上调用getObject方法直接获取LocalDate对象.

    LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;
    

    同样,调用PreparedStatement::setObjectLocalDate 对象传递给数据库中的SQL DATE type 列。

    myPreparedStatement.setObject( … , localDate ) ;
    

    完全避免使用java.sql.Date

    乔达时间

    java.time 包的灵感来自 Joda-Time 库。您可以在 java.time 不可用的早期 Java 版本中使用它。 Joda-Time 也提供 LocalDate 课程。

    【讨论】:

    • 如果驱动程序实现了这个,你只能在 JDBC 4.2 中获得LocalDate
    • @MarkRotteveel 您的评论不正确。 重新阅读我的答案。您可以通过 LocalDate 类的工厂方法或通过在 java.sql.Date 对象上调用 toLocalDate 来获取 LocalDate 对象。这两条路线都与您的 JDBC 驱动程序无关。我的回答解释了与您的 JDBC 驱动程序相关的唯一部分,即在 ResultSet 上调用 getObject。注意大标题“JDBC 4.2 Driver”。
    • 我的评论正是指您帖子的那一部分,这就是为什么我包含“在 JDBC 4.2 中”:使用getObject 获取LocalDate(或setObject 设置一个)仅当驱动程序实现已经支持 Java 8 并遵循 JDBC 4.2 中的要求时才有效。我本来可以更具体一点,但我认为这是您帖子中唯一提到 JDBC 4.2 的部分,提到 JDBC 4.2 就足够了。
    • @MarkRotteveel 看来我在这里误解了你的 cmets 的意思,早在什么时候。但我还是不明白。您是说 JDBC 4.2 中对LocalDate 的支持是可选的吗?在我阅读规范时,似乎需要支持LocalDate。如果我在那里错了,请纠正我;如果可能,请引用规范。如果我仍然不明白这里的 cmets 的意思,请纠正我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 2021-06-16
    相关资源
    最近更新 更多