【问题标题】:Compare dates ignoring milliseconds?比较忽略毫秒的日期?
【发布时间】:2012-08-07 10:58:55
【问题描述】:

有没有办法比较两个日历对象,但忽略毫秒?

我写了一个比较两个日历对象的测试用例,但是有一个问题。尽管所有天、月、分钟和小时都匹配,但毫秒不匹配。我在得到实际日期之前得到了预期日期:

/**
 * @return
 */
private Calendar getExpectedOneMonthDateFromCurrentDate() {
    Calendar expectedOneMonth = Calendar.getInstance();
    expectedOneMonth.add(Calendar.MONTH, -1);
    return expectedOneMonth;
}

assertEquals(getExpectedOneMonthDateFromCurrentDate(),
             DateRange.LAST_ONE_MONTH.getToDate());

【问题讨论】:

  • 为什么不在检查时将毫秒设置为 0?您也可能只获得日期的长值,四舍五入到 1000 秒并进行比较。顺便说一句,您可能会考虑使用 Joda Time 来获得更简单、更一致的时间 API(类似的 API 将成为 Java 8 的一部分)
  • 检查此链接,它可能会有所帮助stackoverflow.com/questions/1671001/…
  • 我以前用过joda time,相信你我希望我能用它

标签: java datetime calendar


【解决方案1】:

从您的日历中删除毫秒

cal.set(Calendar.MILLISECOND, 0);

【讨论】:

  • Thomas 或 Mishadoff 解决方案存在问题。请看我的帖子。
  • 我认为作者只想忽略毫秒。在这种情况下,我们的时间是离散的,等于 1 秒。
  • 谢谢我会试试这个。我只想比较天、月、年、小时和可能的分钟
【解决方案2】:

如果您使用的是 Java 8,则可以使用 Java Time API,特别是 Calendar::toInstant(),然后是 Instant::truncatedTo()。使用ChronoUnit枚举指定截断粒度。

myCalendar.toInstant().truncatedTo( ChronoUnit.SECONDS )  // Lop off any fractional second.

示例。

    Calendar oneMonthIsh = Calendar.getInstance();
    oneMonthIsh.add(Calendar.MONTH, -1);
    oneMonthIsh.add(Calendar.MINUTE, 1);

    assertNotEquals(oneMonthIsh.toInstant(), getExpectedOneMonthDateFromCurrentDate());
    assertEquals(oneMonthIsh.toInstant().truncatedTo(ChronoUnit.DAYS),getExpectedOneMonthDateFromCurrentDate().toInstant()
    .truncatedTo(ChronoUnit.DAYS));

【讨论】:

  • 很好的答案,但它忽略了时区在确定日期和全天计数方面的关键问题。但是这个问题很不清楚,所以正确的方法应该是什么并不明显。如果日历日期很重要,请将Calendar 对象(如果实际上是GregorianCalendar 下面的对象)转换为ZonedDateTime 对象。
【解决方案3】:

你需要使用

cal.set(Calendar.MILLISECOND, 0);

也许还有

cal.set(Calendar.SECOND, 0);

如果你只需要分钟来匹配。

【讨论】:

    【解决方案4】:

    将毫秒设置为 0 的解决方案有一个问题:如果日期为 12:14:29.999 和 12:14:30.003,则将日期分别设置为 12:14:29 和 12:14:30,将检测到您不想检测的差异。

    我想到了一个比较器:

    private static class SecondsComparator implements Comparator<Calendar>
    {
        public int compare(Calendar o1, Calendar o2)
        {
            final long difference = o1.getTimeInMillis() - o2.getTimeInMillis();
            if (difference > -1000 && difference < 1000)
                return 0;
            else
                return difference < 0 ? 1 : -1;
        }
    }
    
    public static void main(String args[])
    {
        Calendar c1 = Calendar.getInstance();
        Utils.waitMilliseconds(100);
        Calendar c2 = Calendar.getInstance();
        // will return 0 
        System.out.println(new SecondsComparator().compare(c1,c2));
    }
    

    但是,它也不是一个好的解决方案,因为这个 Comparator 违反了以下规则:

    实施者必须确保对于所有 z,x.compareTo(y)==0 意味着 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。

    什么导致(x=y and y=z) =&gt; x=z

    所以我没有看到任何解决方案...但实际上,如果您定义一些不同的日期,它们不同的,不是吗?

    【讨论】:

      【解决方案5】:

      一种选择是调用 Calendar.set(Calendar.MILLISECOND, 0) 来清除毫秒。另一种方法是调用 getTimeInMillis() 以获取两个日历的时间(以毫秒为单位)。然后,您可以将它们除以 1000,然后再进行比较以删除毫秒。

      【讨论】:

        【解决方案6】:

        恕我直言,最简单的方法是使用 Apache Commons DateUtils (Apache Commons DateUtils) 中的 truncate() 删除毫秒并比较结果日期。

        【讨论】:

          【解决方案7】:

          如果您要执行基本日期操作之外的任何操作,我建议您使用 Joda Time。在您的情况下,您可以像这样截断日期,然后进行比较:

          DateTime dateTime = new DateTime().millisOfDay().roundFloorCopy();
          

          【讨论】:

          • 这个不行,需要把millisOfDay()换成secondOfDay()
          • 不应该是millisOfSecond()吗?
          【解决方案8】:
          clearMilis(date1).compareTo(clearMilis(date2))
          
          
          /**
           * @param date date
           *
           * @return truncated miliseconds
           */
          @Nonnull
          public static Date clearMillis(final @Nonnull Date date)
          {
              DateTime result = new DateTime(date);
          
              return result.minusMillis(result.getMillisOfSecond()).toDate();
          }
          

          【讨论】:

            【解决方案9】:
            public static String getFromatDateTime(Date date) {
                SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
                final GregorianCalendar gc = new GregorianCalendar();
                gc.setTime( date );
                //gc.set( Calendar.HOUR_OF_DAY, 0 );
                //gc.set( Calendar.MINUTE, 0 );
                //gc.set( Calendar.SECOND, 0 );
                //block ignore millisecond 
                gc.set( Calendar.MILLISECOND, 0 );
                String strDate = sdfDate.format(gc.getTime());
                return strDate;
            }
            public static void main(String[] args) throws ParseException {
                SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
                Date now = new  Date();
                String currentDate = Testing.getFromatDateTime(now);
                String fullDate = "2015-12-07 14:53:39.30";
                String effDateStr = Testing.getFromatDateTime(sdfDate.parse(fullDate));
            
                System.out.println("Currennt Date: " + currentDate);
                System.out.println("Effective Date: " + effDateStr);
                System.out.println(currentDate.compareTo(effDateStr)==0);
            }
            

            【讨论】:

            • 稍微解释一下就好了
            • 好吧,如果我们想忽略毫秒。我们需要通过在函数 getFromatDateTime 中使用 GregorianCalendar 和 Calendar 将毫秒设置为 0,就像这样 gc.set(Calendar.MILLISECOND, 0)。哦,我的代码是使用类测试
            【解决方案10】:

            如果使用 jodaTime,setCopy("0") 方法会返回一个 DateTime 对象,其毫秒设置为 0,以便于比较:

            DateTime dateTimeZerodMillis = new DateTime().millisOfSecond ().setCopy("0")
            

            【讨论】:

              【解决方案11】:

              虽然我来晚了,但为后代分享我的简单替代方法

              使用org.apache.commons.lang3.time.DateUtils 忽略毫秒来比较两个日期对象

              Date date1 = new Date(1503055069000L);
              Date date2 = new Date(1503055069683L);
              //Here the two dates are differed by 683 milliseconds, if we want to skip just the 
              //683 milliseconds difference then we can use the below logic
              if(DateUtils.setMilliseconds(date1, 0).equals(DateUtils.setMilliseconds(date2, 0))){
                  //your business process
                
              }
              

              注意DateUtils#setMilliseconds 方法将毫秒字段设置为返回新对象的日期。 原日期不变。因此,在您重新分配对象引用之前,原始日期对象值保持不变。

              【讨论】:

                猜你喜欢
                • 2011-10-25
                • 1970-01-01
                • 1970-01-01
                • 2018-07-28
                • 2011-08-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多