首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java8- ChronoUnit.MONTHS.between(fromDate,toDate)不能按预期工作

Java8- ChronoUnit.MONTHS.between(fromDate,toDate)不能按预期工作
EN

Stack Overflow用户
提问于 2018-06-17 02:19:25
回答 2查看 7.9K关注 0票数 5

我要找出不是。两个日期之间的月份,包括首尾两个月。我正在使用ChronoUnit.Months.between,但得到了意想不到的结果。

代码适用范围:1月31日-7月31日

失败时间:1月31 -6月30日

失败的代码:

代码语言:javascript
复制
import java.time.LocalDate;
import static java.time.temporal.ChronoUnit.MONTHS;
public class HelloWorld{

     public static void main(String []args){
        LocalDate startDate=LocalDate.of(2018,01,31);
        LocalDate endDate=LocalDate.of(2018,6,30);
        //Both dates inclusive, hence adding 1
        long noOfMonths = (MONTHS.between(startDate,endDate)) + 1L;
        System.out.println(" ********* No. of months between the two dates : " + noOfMonths);
        }
}

预期:6(1,2,3,4,5,6)实际:5

有效的代码:

代码语言:javascript
复制
import java.time.LocalDate;
import static java.time.temporal.ChronoUnit.MONTHS;
public class HelloWorld{

     public static void main(String []args){
        LocalDate startDate=LocalDate.of(2018,01,31);
        LocalDate endDate=LocalDate.of(2018,7,31);
        //Both dates inclusive, hence adding 1
        long noOfMonths = (MONTHS.between(startDate,endDate)) + 1L;
        System.out.println(" ********* No. of months between the two dates : " + noOfMonths);
        }
}

预期:7(1,2,3,4,5,6,7)实际:7

你看到同样的行为了吗?有没有什么替代的方法呢?

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-17 14:40:45

半开

另外两个答案by davidxxxby Ole V.V.都是正确且信息丰富的。

我想补充一下在日期-时间工作中常用的另一种定义时间跨度的方法:半开放。在半开放方法中,开始是包容性的,而结尾是排他性的。因此,今年上半年的月份( 1月、2月、3月、4月和6月)被跟踪为从1月1日开始,一直到(但不包括)7月1日。

有时我们会在日常生活中直观地使用这种方法。例如,如果一个教室的孩子们从中午12点到下午1点休息吃午饭,那么学生们应该在下午1点的钟声敲响之前回到座位上。午休时间持续到下午1点,但不包括下午1点

我相信您会发现,始终如一地使用Half-Open方法会使您的代码更易于阅读、调试和维护。

现代的java.time类使用这种方法来定义时间跨度。

LocalDateRange

Ole V.V.的回答明智地建议您使用YearMonth类来帮助您的工作。

另一个有用的类来自项目:org.threeten.extra.LocalDateRange。您可以在单个对象中表示整个日期范围。

您可以使用开始日期和六个月的Period实例化。

代码语言:javascript
复制
LocalDateRange ldr = LocalDateRange.of( 
    LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
    Period.ofMonths( 6 ) 
) ;

或者指定开始日期和停止日期。

代码语言:javascript
复制
LocalDateRange ldr = LocalDateRange.of( 
    LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
    LocalDate.of( 2018 , Month.JULY , 1 ) // Half-open.
) ;

虽然我不推荐这样做,但如果您坚持使用完全封闭的方法,即开始和结束都包含在内,那么LocalDateRange确实提供了LocalDateRange.ofClosed()

代码语言:javascript
复制
LocalDateRange ldr = LocalDateRange.ofClosed(     // `ofClosed` vs `of`.
    LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
    YearMonth( 2018 , Month.JUNE ).atEndOfMonth() // Fully-closed.
) ;

您可以通过Period类从LocalDateRange获取月数。

代码语言:javascript
复制
LocalDateRange ldr = LocalDateRange.of( 
    LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
    Period.ofMonths( 6 ) 
) ;
Period p = ldr.toPeriod() ; 
long totalMonths = p.toTotalMonths() ;  // 6

关于java.time

框架内置于Java8和更高版本中。这些类取代了麻烦的旧legacy日期时间类,如java.util.DateCalendarSimpleDateFormat

现在在maintenance mode中的项目建议迁移到java.time类。

要了解更多信息,请参阅。和搜索堆栈溢出,以获得许多示例和解释。规范为JSR 310

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC driver。不需要字符串,也不需要java.sql.*类。

从哪里获取java.time类?

内置

  • ,、和更高版本的
    • 。与implementation.
    • Java 9捆绑在一起的标准Java API的
    • 部分添加了一些次要功能和fixes.

  • 和.

中的

  • 许多java.time功能已向后移植到Java6和7

    • 更高版本的Android捆绑实现的java.time类。
    • 对于较早的Android (<26),项目适配 (如上所述)。请参阅.

项目使用额外的类扩展了java.time。这个项目是未来可能添加到java.time中的试验场。您可能会在这里找到一些有用的类,如IntervalYearWeekYearQuartermore

票数 5
EN

Stack Overflow用户

发布于 2022-03-02 16:01:14

其他解决方案:

代码语言:javascript
复制
int getInclusiveMonthsDiff(LocalDate startDate, LocalDate endDate) {
        return (endDate.monthValue + endDate.year * 12) - (startDate.monthValue + startDate.year * 12) + 1
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50890562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档