11

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

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

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

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

11 回答 11

18

Remove milliseconds from your calendar

cal.set(Calendar.MILLISECOND, 0);
于 2012-08-07T11:02:14.073 回答
4

你需要使用

cal.set(Calendar.MILLISECOND, 0);

也可能

cal.set(Calendar.SECOND, 0);

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

于 2012-08-07T11:03:06.827 回答
3

将毫秒设置为 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 违反了以下规则:

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

什么导致(x=y and y=z) => x=z

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

于 2012-08-07T14:03:07.703 回答
2

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

于 2012-08-07T11:07:24.313 回答
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));
于 2019-08-15T18:03:38.833 回答
1

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

于 2012-08-07T11:03:20.760 回答
0

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

DateTime dateTime = new DateTime().millisOfDay().roundFloorCopy();
于 2012-08-07T11:31:41.560 回答
0
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();
}
于 2013-04-25T18:40:40.147 回答
0
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);
}
于 2015-12-08T02:18:10.000 回答
0

虽然我参加聚会为时已晚,但为后代分享我的简单替代方法

通过使用忽略毫秒来比较两个日期对象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方法将毫秒字段设置为返回新对象的日期。原始日期不变。因此,在您重新分配对象引用之前,原始日期对象值保持不变。

于 2021-08-13T10:12:52.330 回答
0

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

DateTime dateTimeZerodMillis = new DateTime().millisOfSecond ().setCopy("0")
于 2016-10-05T22:28:01.413 回答