【问题标题】:Comparing two dates from different format比较不同格式的两个日期
【发布时间】:2019-10-03 06:57:24
【问题描述】:

如何比较这两个不同格式的日期以检查它们是否相等

Date d1 = bean.fooDate; // >> from a post request
System.out.println(d1); // >> "Sat May 25 10:00:00 WET 2019"

Date d2 = fooEntity.getFooDate(); // >> from mysql database
System.out.println(d2); // >> "2019-05-25"

P.S 我只想将它作为日期而不是日期时间进行比较(无需比较分钟和秒数)

【问题讨论】:

    标签: java spring hibernate spring-mvc jpa


    【解决方案1】:

    说你的两个日期有不同的格式并不准确。 Date 没有格式。你看到你打印的日期是他们toString方法的返回值。

    相反,您的日期有不同的运行时类型。 d1 是java.util.Date 的一个实例,它的toString 方法生成Sat May 25 10:00:00 WET 2019 格式。 d2又是java.sql.Date的一个实例。它是java.util.Date 的子类,因此可以分配给这种类型的变量。 java.sql.Date.toString() 生成格式 2019-05-25。但是,子类(继承)关系是一种你不应该在代码中依赖的技巧。

    不过,继承黑客只是这两个类的众多设计问题之一。幸运的是,两者都存在更新和更现代的替代品。对于java.util.Date,现代Instant 类是最直接对应的类型,但具体使用哪一种取决于您更精确的要求。对于java.sql.Date,它更简单,使用LocalDate。 Instant 和 LocalDate 都是现代 Java 日期和时间 API java.time 的一部分。

    所以看看你是否可以用 Instant 或 java.time 中的其他合适的现代类型替换 bean.fooDate。同样,看看您是否可以让fooEntity.getFooDate() 返回LocalDate。 Hibernate 应该很乐意为您处理 LocalDate 而不是 Date(除非您的 Hibernate 版本非常旧)。

    在任何情况下,Srinivasan Sekar 都是正确的,您应该将您从每个获得的任何类型转换为 LocalDate 以仅比较日期而不是小时、分钟和秒。 LocalDate 就是这样:一个没有时间的日期。

    假设您从bean.fooDate 获得Instant。那么转换为:

        LocalDate localDate1 = bean.fooDate.atZone(ZoneId.of("Africa/El_Aaiun")).toLocalDate();
    

    请务必指定适当的时区。

    如果您无法避免老式的Date,那么 Srinivasan Sekar 的答案中的转换是正确的:

        LocalDate localDate1 = bean.fooDate
                .toInstant()
                .atZone(ZoneId.of("Africa/El_Aaiun"))
                .toLocalDate();
    

    对于fooEntity.getFooDate() 的情况,如果你能得到上面提到的LocalDate,你就完成了。如果只能得到Date,首先检查方法是否声明为返回java.util.Date 或java.sql.Date。它可能取决于声明方法的文件中使用的导入。 java.sql.Date 的情况很简单(尽管不幸的是不能保证总是给出正确的日期):

        LocalDate localDate2 = fooEntity.getFooDate().toLocalDate();
    

    如果声明的返回类型是java.util.Date,您可以只在上面添加一个强制转换,因为看起来实际返回的对象是java.sql.Date。不过,首先测试您的假设会更安全:

        LocalDate localDate2;
        Date d2 = fooEntity.getFooDate();
        if (d2 instanceof java.sql.Date) {
            localDate2 = ((java.sql.Date) fooEntity.getFooDate()).toLocalDate();
        } else {
            localDate2 = d2.toInstant()
                    .atZone(ZoneId.of("Africa/El_Aaiun"))
                    .toLocalDate();
        }
    

    您会发现,在第二种情况下,我使用的转换与上述相同。

    比较生成的LocalDate 变量:

        if (localDate1.isEqual(localDate2)) {
            System.out.println("Same date");
        } else {
            System.out.println("Different dates");
        }
    

    LocalDate 也有方法 isBefore 和 isAfter 以防您需要确定哪个更早。

    链接: Oracle tutorial: Date Time 解释如何使用 java.time。

    【讨论】:

      【解决方案2】:

      使用 java 8 中的toLocalDate() 单独比较日期部分

      LocalDate localDate1=date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
      LocalDate localDate2=date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
      localDate1.compareTo(localDate2)
      

      【讨论】:

      • 我收到了这个错误java.lang.UnsupportedOperationException at java.sql.Date.toInstant(Date.java:304)
      • 日期应该是 util.date 兄弟。不知道你在使用 sql.date。
      • 你们俩的日期都是 java.sql.date 吗? @优素福
      • 不,它们来自java.util.Date,我不明白它何时来自java.sql.Date,可能是因为我正在使用休眠??
      • LocalDate localDate1 = date1 instanceof java.sql.Date ? ((java.sql.Date) date1).toLocalDate() : date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();。 date2 也是如此(实际上,d2 可能只需要问题)。
      【解决方案3】:

      Date 对象有一个方法 getTime(),它返回自 1970 年 1 月 1 日以来的毫秒数 (see the docs)。

      所以,比较两个日期:

      if (d1.getTime() == d2.getTime()) {
          // the dates represent the same point in time
      } else {
          // they are different points in time
      }
      

      您还可以使用此技术来查看一个使用< 或> 是在另一个之前还是之后。

      编辑:如果要比较日期而不考虑时间分量,只需将getTime() 返回的每个值除以一天中的毫秒数(1000 * 60 * 60 * 24 ):

      long millisInADay = 1000 * 60 * 60 * 24;
      long m1 = d1.getTime() / millisInADay;
      long m2 = d2.getTime() / millisInADay;
      
      if (m1 == m2) {
          // the two dates (excluding time) are the same
      } else {
          // they're not
      }
      

      【讨论】:

      • getTime()没用给了我两个不同的值1558742400000和1558778400000
      • 编辑删除时间因素,只比较日期。
      • 只有当询问者的时区与 UTC 一致时,除以一天中的毫秒数才能正常工作,而很少有时区这样做。它也非常手动,因此不容易阅读。
      • It works incorrectly in your time zone and in mine; this is a link to a live demo (可能最容易先读取输出,然后读取代码)。
      • 感谢您对我的回答投反对票。如果那是你。这只是一个怀疑,我不知道。是我拒绝了你的投票,我相信我已经解释了原因。
      猜你喜欢
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-16
      • 1970-01-01
      • 2022-11-17
      相关资源
      最近更新 更多