在Java 8中计算两个日期之间的天数

371

我知道SO上有很多关于如何在Java中获取Date的问题,但我想要一个使用新的Java 8 Date API的示例。我也知道JodaTime库,但我想要一种不依赖外部库的方法。

这个函数需要遵守以下限制:

  1. 防止日期保存时间引起的错误
  2. 输入是两个Date对象(没有时间,我知道LocalDateTime,但我需要使用Date实例来完成此操作)

3
类似于这个例子的东西? - MadProgrammer
2
@MadProgrammer 不是很合适 - Duration 不是最好的选择来做那件事... - assylias
@assylias 嗯,这比原帖好。 - MadProgrammer
@assylias 那是什么? - MadProgrammer
18
@MadProgrammer DAYS.between(localDate1, localDate2) - assylias
14个回答

617
如果你想要“逻辑日历天数”,可以使用DAYS.between()方法,该方法来自于java.time.temporal.ChronoUnit
LocalDate dateBefore;
LocalDate dateAfter;
long daysBetween = DAYS.between(dateBefore, dateAfter);

如果你想要字面上的24小时天数(一个持续时间),你可以使用Duration类来代替:
LocalDate today = LocalDate.now()
LocalDate yesterday = today.minusDays(1);
// Duration oneDay = Duration.between(today, yesterday); // throws an exception
Duration.between(today.atStartOfDay(), yesterday.atStartOfDay()).toDays() // another option

更多信息,请参考此文档:Java SE 8日期和时间

29
这会抛出异常,因为Duration.between方法需要支持SECONDS单位的时间对象。请尝试使用Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays()代替。 - VGR
7
你可以使用 today.atStartOfDay() 替代 today.atTime(0, 0) - eee
5
@REACHUS 或许给出 -1 的评价有点过于苛刻了,因为你提供的代码确实可用,但 Duration 应该是用于“基于时间的时间量度量”。有一种内置的方式可以衡量一定数量的天数,它不需要将日期转换为日期时间。 - assylias
6
更好的答案是下面 @Sunil B 的回答:ChronoUnit.DAYS.between(firstDate, secondDate),用于计算 LocalDate 之间的天数差。 - Paul
1
@Lappro为什么更好?它使用了与我的答案相同的方法。 - syntagma
@syntagma 哦,你的第一个例子确实是一样的,我没有看到那是因为 DAYS 是从一个导入中来的,而不是 ChronoUnit.DAYS。匆忙地寻找快速解决方案并不总是我的最佳策略 ;) - Paul

194
基于VGR在此的评论,以下是您可以使用的内容:
ChronoUnit.DAYS.between(firstDate, secondDate)

9
这个解决方案应该被采纳为最佳答案,因为它更为简洁。 - S. Pauk

62
您可以使用until
LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4);
LocalDate christmas = LocalDate.of(2014, Month.DECEMBER, 25);

System.out.println("Until christmas: " + independenceDay.until(christmas));
System.out.println("Until christmas (with crono): " 
   + independenceDay.until(christmas, ChronoUnit.DAYS));

输出:

Until christmas: P5M21D
Until christmas (with crono): 174

如评论中所述,如果未指定单位,则until返回Period

来自文档的片段:

ISO-8601日历系统中基于日期的时间量,例如“2年3个月4天”。
此类以年、月和日的形式对时间数量或金额进行建模。有关此类的基于时间的等效项,请参见Duration。


9
我刚刚使用的第一版“until”的问题在于它返回一个Period对象。这将返回两个日期之间的年/月/日数,而不是实际天数。而Period对象的getDays()方法仅返回天数部分(不考虑年或月的数量),而不是总天数。第二个版本正如期望的那样可以得到两个日期之间的天数。 - M. Justin
有没有完整的替代方案?因为它需要 Android SDK 26 及以上版本。 - ralphgabb

23

DAYS.between

您可以使用来自java.time.temporal.ChronoUnitDAYS.between

例如:

import java.time.temporal.ChronoUnit;
...

long totalDaysBetween(LocalDate dateBefore, LocalDate dateAfter) {
    return DAYS.between(dateBefore, dateAfter);

19

如果 startDateendDatejava.util.Date 的实例

我们可以使用 ChronoUnit 枚举的 between( ) 方法:

public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
    //..
}

ChronoUnit.DAYS用于计算已经完成了24小时的天数。

import java.time.temporal.ChronoUnit;

ChronoUnit.DAYS.between(startDate.toInstant(), endDate.toInstant());

//OR 

ChronoUnit.DAYS.between(Instant.ofEpochMilli(startDate.getTime()), Instant.ofEpochMilli(endDate.getTime()));

11
使用 Java 中的枚举类型 java.time.temporal.ChronoUnit 中的 DAYS。以下是示例代码:

输出: *2015-03-01 到 2016-03-03 的天数为:368。 **2016-03-03 到 2015-03-01 的天数为:-368*

输出: *2015-03-01 到 2016-03-03 的天数为:368。 **2016-03-03 到 2015-03-01 的天数为:-368*

package com.bitiknow.date;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

/**
 * 
 * @author pradeep
 *
 */
public class LocalDateTimeTry {
    public static void main(String[] args) {

        // Date in String format.
        String dateString = "2015-03-01";

        // Converting date to Java8 Local date
        LocalDate startDate = LocalDate.parse(dateString);
        LocalDate endtDate = LocalDate.now();
        // Range = End date - Start date
        Long range = ChronoUnit.DAYS.between(startDate, endtDate);
        System.out.println("Number of days between the start date : " + dateString + " and end date : " + endtDate
                + " is  ==> " + range);

        range = ChronoUnit.DAYS.between(endtDate, startDate);
        System.out.println("Number of days between the start date : " + endtDate + " and end date : " + dateString
                + " is  ==> " + range);

    }

}

11

大家都说要用ChronoUnit.DAYS.between,但它只是委托给另一个你可以自己调用的方法。所以你也可以这样做:firstDate.until(secondDate, ChronoUnit.DAYS)

实际上,两种方法的文档都提到了,并且建议使用更易读的那种。


就我而言...我不确定为什么两者都存在。是否有时候一个更易读,而另一个则更好?何时/为什么? - nafg

7

从当前日期获取距离圣诞节的天数,试试这个方法:

System.out.println(ChronoUnit.DAYS.between(LocalDate.now(),LocalDate.of(Year.now().getValue(), Month.DECEMBER, 25)));

6

请看下面:

public class DemoDate {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        System.out.println("Current date: " + today);

        //add 1 month to the current date
        LocalDate date2 = today.plus(1, ChronoUnit.MONTHS);
        System.out.println("Next month: " + date2);

        // Put latest date 1st and old date 2nd in 'between' method to get -ve date difference
        long daysNegative = ChronoUnit.DAYS.between(date2, today);
        System.out.println("Days : "+daysNegative);

        // Put old date 1st and new date 2nd in 'between' method to get +ve date difference
        long datePositive = ChronoUnit.DAYS.between(today, date2);
        System.out.println("Days : "+datePositive);
    }
}

4

获取两个日期之间的天数,其中date是java.util.Date实例

public static long daysBetweenTwoDates(Date dateFrom, Date dateTo) {
            return DAYS.between(Instant.ofEpochMilli(dateFrom.getTime()), Instant.ofEpochMilli(dateTo.getTime()));
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接