10

我已经看到了很多关于这个主题的问题和答案,但没有一个解决我的特定问题。我扩展了 java Calendar 类(标准——没有第三方库),并且需要找出两个任意日期之间的天数差异。

方法:

  1. 将两个日期的时间更改为午夜。
  2. 将日期转换为毫秒。
  3. 找出两个日期之间的差异。
  4. 将结果除以一天中的毫秒数 (24 * 60 * 60 * 1000)。
  5. 结果应该是天的差异。

有时是,有时不是。即使是同一天的测试也可以减少一个。这是怎么回事?

4

7 回答 7

11

Joda Time Library对此类问题有很好的支持:

LocalDate d1 = new LocalDate(calendar1.getTimeInMillis());
LocalDate d2 = new LocalDate(calendar2.getTimeInMillis());
int days = Days.daysBetween(d1, d2).getDays();

更新(来自@basil-bourque 的反馈):

从 Java 8java.time开始,引入了新的时间库,现在可以使用没有外部依赖项的类似选项:

int days = Duration.between(calendar1.toInstant(), calendar2.toInstant()).toDays();
于 2012-11-02T17:08:26.473 回答
6

正如其他用户所建议的,您还需要将日历的毫秒值设置为零以仅比较日期。这可以通过以下代码片段来实现:

someCalendar.set(Calendar.MILLISECOND, 0)

另外,请注意时区变化(例如从冬季时间到夏季时间)可能意味着一天的时间多于或少于 86,400,000 毫秒。

于 2012-11-06T20:40:36.277 回答
6
于 2017-03-02T02:22:43.290 回答
4

我已经写了一种更简单的方法来解决这个问题,即使我也面临同样的问题,即某些日期要多出一天。

这是我目前的做法,

    public long getDays(long currentTime, long endDateTime) {

    Calendar endDateCalendar;
    Calendar currentDayCalendar;


    //expiration day
    endDateCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
    endDateCalendar.setTimeInMillis(endDateTime);
    endDateCalendar.set(Calendar.MILLISECOND, 0);
    endDateCalendar.set(Calendar.MINUTE, 0);
    endDateCalendar.set(Calendar.HOUR, 0);

    //current day
    currentDayCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
    currentDayCalendar.setTimeInMillis(currentTime);
    currentDayCalendar.set(Calendar.MILLISECOND, 0);
    currentDayCalendar.set(Calendar.MINUTE, 0);
    currentDayCalendar.set(Calendar.HOUR, 0);

    long remainingDays = Math.round((float) (endDateCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis()) / (24 * 60 * 60 * 1000));

    return remainingDays;
}

以前我用的是这条线,其余的都是一样的:-

long remainingDays = TimeUnit.MILLISECONDS.toDays(
            Math.abs(expiryCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis()));

但似乎不适合我。

于 2017-04-13T09:59:26.523 回答
2

您在第一步中通过将时间设置为午夜来识别问题:确保所有小时、分钟和秒都为零。但你走得还不够远!您还必须确保毫秒也被归零。

这里有一些代码可以做到这一点。

protected long truncate_to_seconds (long date_in_millis) {
    long l = date_in_millis / 1000L;
    l *= 1000L;
    return l;
} 
于 2012-11-02T15:46:17.800 回答
1

我相信您需要在计算差异之前从日期截断时间部分,如下所示:

   DateFormat formatter= new SimpleDateFormat("MM/dd/yyyy");
   String truncatedDateString1 = formatter.format(date1);
   Date truncatedDate1 = formatter.parse(truncatedDateString1);

   String truncatedDateString2 = formatter.format(date2);
   Date truncatedDate2 = formatter.parse(truncatedDateString2);

   long timeDifference = truncatedDate2.getTime()- truncatedDate1.getTime();

   int daysInBetween = timeDifference / (24*60*60*1000);

希望这有效。

于 2012-11-02T15:57:05.657 回答
0

根据您的要求,我有我的职责。我正在使用日历,在比较之前我将所有时间部分设置为 0。

    int countDays(Date dateBegin, Date dateEnd) {
    if (dateBegin == null || dateEnd == null)
        return 0;
    Calendar from = asCalendar(dateBegin); // asCalendar() Initialise a Calendar from a Date
    Calendar to = asCalendar(dateEnd);
    // Set the time part to 0
    from.set(Calendar.MILLISECOND, 0);
    from.set(Calendar.SECOND, 0);
    from.set(Calendar.MINUTE, 0);
    from.set(Calendar.HOUR_OF_DAY, 0);
    to.set(Calendar.MILLISECOND, 0);
    to.set(Calendar.SECOND, 0);
    to.set(Calendar.MINUTE, 0);
    to.set(Calendar.HOUR_OF_DAY, 0);
    int nbJours = 0;
    for (Calendar c = from ; c.before(to) ; c.add(Calendar.DATE, +1))
    {
        nbJours++;
    }
    for (Calendar c = from ; c.after(to) ; c.add(Calendar.DATE, -1))
    {
        nbJours--;
    }
    return nbJours;
    }
于 2014-08-29T06:58:47.560 回答