Joda-Time中两个date之间的天数

如何查找两个Joda-Time DateTime实例之间的天数差异? 我认为如果开始是星期一,结束是星期二,我认为无论开始和结束date是小时还是分钟/秒,返回值都是1。

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

我也有与其他date字段相同的问题,所以我希望有一个通用的方式来“忽略”较小的意义的领域。

换句话说,二月至四月四日之间的月份也是一点,14:45至15:12之间的时间也是一点。 不过14:01和14:55之间的小时差是0。

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

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

事实certificate,“午夜/开始的一天”有时意味着凌晨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去避开整个问题。

Days

使用Days类与withTimeAtStartOfDay方法应该工作:

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

你可以使用LocalDate

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

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项目现在处于维护模式 ,团队build议迁移到java.time类。

Joda-Time DateTime的等价物是ZonedDateTime

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

显然你想按date来计算date,这意味着你想忽略一天的时间。 例如,在午夜前一分钟开始,在午夜后一分钟结束,应该导致一天。 对于这种行为,从ZonedDateTime提取一个LocalDateLocalDate类代表没有时间和没有时区的只有date的值。

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

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

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

截短

至于你问一个更一般的方法来做这个计算你感兴趣的小时数的时差为六十分钟的时间跨度,而不是完整的小时,使用truncatedTo方法。

这是你同一天14:45到15:12的例子。

 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 ) ); 

1

按date计算天数,截断为ChronoUnit.DAYS 。 这是一个例子,从五分钟前到五分钟后的午夜,经过一天的时间是1

 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 ) ); 

1


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧的遗留date时间类,如java.util.DateCalendarSimpleDateFormat

Joda-Time项目现在处于维护模式 ,build议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并search堆栈溢出了很多例子和解释。 规范是JSR 310 。

从何处获取java.time类?

  • Java SE 8Java SE 9和更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6Java SE 7
    • 大部分的java.timefunction都被移植到了ThreeTen-Backport中的 Java 6&7中。
  • Android的
    • ThreeTenABP项目专门针对Android,采用了ThreeTen-Backport (上文提到)。
    • 请参阅如何使用ThreeTenABP …。

ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 你可能会在这里find一些有用的类,比如IntervalYearWeekYearQuarter 等等 。

接受的答案构build两个LocalDate对象,如果您正在阅读大量数据,则这些对象相当昂贵。 我使用这个:

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

通过调用getMillis()您可以使用已经存在的variables。
MILLISECONDS.toDays()然后,使用一个简单的算术计算,不创build任何对象。

 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; }