Joda-Time中两个日期之间的天数

时间:2010-09-27 10:21:31

标签: java date jodatime

如何找到两个Joda-Time DateTime个实例之间的天数差异? “天数差异”是指如果开始时间是星期一而结束时间是星期二,那么无论开始日期和结束日期的小时/分钟/秒如何,我都希望返回值为1。

Days.daysBetween(start, end).getDays()如果开始是在晚上并在早上结束,则给我0。

我也遇到了与其他日期字段相同的问题,所以我希望有一种通用的方法来“忽略”不太重要的字段。

换句话说,2月到3月4日之间的月份也是1,而14:45到15:12之间的时间也是1。但是,14:01和14:55之间的小时差异为0。

8 个答案:

答案 0 :(得分:367)

令人讨厌的是,withTimeAtStartOfDay的答案是错误的,但只是偶尔。你想要:

Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()

事实证明,“午夜/一天开始”有时意味着凌晨1点(在某些地方以这种方式进行夏令时),Days.daysBetween无法正常处理。

// 5am on the 20th to 1pm on the 21st, October 2013, Brazil
DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo");
DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL);
DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL);
System.out.println(daysBetween(start.withTimeAtStartOfDay(),
                               end.withTimeAtStartOfDay()).getDays());
// prints 0
System.out.println(daysBetween(start.toLocalDate(),
                               end.toLocalDate()).getDays());
// prints 1

通过LocalDate回避整个问题。

答案 1 :(得分:183)

Days Class

使用Days类和withTimeAtStartOfDay方法应该有效:

Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays() 

答案 2 :(得分:83)

您可以使用LocalDate

Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays() 

答案 3 :(得分:6)

TL;博士

java.time.temporal.ChronoUnit.DAYS.between( 
    earlier.truncatedTo( ChronoUnit.DAYS )  , 
    later.truncatedTo( ChronoUnit.DAYS ) 
)

...或...

java.time.temporal.ChronoUnit.HOURS.between( 
    earlier.truncatedTo( ChronoUnit.HOURS )  , 
    later.truncatedTo( ChronoUnit.HOURS ) 
)

java.time

仅供参考,Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time课程。

相当于Joda-Time DateTimeZonedDateTime

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

显然,您希望按日期计算天数,这意味着您要忽略一天中的时间。例如,在午夜前一分钟开始到午夜后一分钟结束应该会导致一天。对于此行为,请从LocalDate中提取ZonedDateTimeLocalDate类表示没有时间且没有时区的仅限日期的值。

LocalDate localDateStart = zdtStart.toLocalDate() ;
LocalDate localDateStop = zdtStop.toLocalDate() ;

使用ChronoUnit枚举来计算已用天数或其他单位。

long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;

截断

至于你问一个更通用的方法来计算你感兴趣的地方的小时数增量作为时钟的时间而不是60小时的跨度的完整时间,使用{{ 1}}方法。

以下是同一天14:45至15:12的例子。

truncatedTo
  

1

按日期计算天数,截断为ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z ); ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z ); long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) ); 。以下为ChronoUnit.DAYS经过的天数,从前五分钟到五分钟后午夜滚动的示例。

1
  

1

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 23 , 55 , 0 , 0 , z ); ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 18 , 00 , 05 , 0 , 0 , z ); long days = ChronoUnit.DAYS.between( start.truncatedTo( ChronoUnit.DAYS ) , stop.truncatedTo( ChronoUnit.DAYS ) ); 类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 4 :(得分:2)

接受的答案构建了两个LocalDate对象,如果您正在阅读大量数据,这些对象非常昂贵。 我用这个:

  public static int getDaysBetween(DateTime earlier, DateTime later)
  {
    return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
  }

通过调用getMillis(),您可以使用已有的变量 MILLISECONDS.toDays()然后,使用简单的算术计算,不会创建任何对象。

答案 5 :(得分:1)

java.time.Period

使用java.time.Period类来count days

由于Java 8使用LocalDateLocalDateTime来表示两个日期更容易计算出差异

    LocalDate now = LocalDate.now();
    LocalDate inputDate = LocalDate.of(2018, 11, 28);

    Period period = Period.between( inputDate, now);
    int diff = period.getDays();
    System.out.println("diff = " + diff);

答案 6 :(得分:0)

DateTime  dt  = new DateTime(laterDate);        

DateTime newDate = dt.minus( new  DateTime ( previousDate ).getMillis());

System.out.println("No of days : " + newDate.getDayOfYear() - 1 );    

答案 7 :(得分:-11)

public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}