收集一段时间内每个月的天数

Collect the number of days per month in each month in a span of time

我被困在这几天我搜索了很多,我在 java swing 程序中使用 jodatime 库 所以这就是我需要的 从 2013-04-17 到 2013-05-21 我需要这样输出结果:

我尝试了很多但没有解决方案,很生气:(删除所有代码并来到这里寻求帮助 任何帮助,将不胜感激。提前致谢

java.time

Joda-Time team has advised us to migrate to the java.time framework built into Java 8 and later. Much of the java.time framework has been back-ported to Java 6 & 7 and further adapted to Android.

LocalDate class 表示没有时间和时区的仅日期值。

LocalDate start = LocalDate.parse ( "2013-04-17" );
LocalDate stop = LocalDate.parse ( "2013-05-21" );
if ( stop.isBefore ( start ) ) {
    System.out.println ( "ERROR - stop before start" );
    // FIXME: Handle error.
}

YearMonth class 表示一年和一个月的总和。非常适合跟踪您想要的结果。使用此 class 可以使您的代码类型安全,并保证有效值,而不是仅使用字符串或数字。

YearMonth startYm = YearMonth.from ( start );
YearMonth stopYm = YearMonth.from ( stop );

我们创建一个 SortedMap where a YearMonth key maps to a Integer value (the number of days) to collect our results. TreeMap 是我们选择的实现。

SortedMap<YearMonth , Integer> map = new TreeMap<> ();

示例代码不假设我们只桥接两个月。如果中间有多个月,我们会询问 YearMonth 该月的天数。我们通过 YearMonth 循环 YearMonth,每次获得天数。

我们对五种可能情况中的每一种进行 if-else 测试:

  • 单月
    • 启停都在一个月内
  • 多个月
    • 第一个月
    • 任何中间月份
    • 上个月
  • 不可能else
    • 除非我们的逻辑或编码有误,否则应该无法到达。

在每种情况下,我们都会获取为该 YearMonth 收集的天数。

调用between方法时,我们必须调整其使用半开方法来处理时间跨度。在这种方法中,开头是 inclusive,而结尾是 exclusive。一般来说,这是最好的路线。但是问题中的逻辑不是这样,所以我们进行调整。我强烈建议撤消这些调整,而是调整您的输入。持续使用半开将使日期时间处理变得更加容易。

YearMonth yearMonth = startYm;
do {
    int days = 0;
    if ( startYm.equals ( stopYm ) ) { // If within the same (single) month.
        days = ( int ) ChronoUnit.DAYS.between ( start , stop );
    } else if ( yearMonth.equals ( startYm ) ) { // If on the first month of multiple months, count days.
        days = ( int ) ChronoUnit.DAYS.between ( start , startYm.plusMonths ( 1 ).atDay ( 1 ) ); //  Get first of next month, to accommodate the `between` method’s use of Half-Open logic.
    } else if ( yearMonth.isAfter ( startYm ) && yearMonth.isBefore ( stopYm ) ) { // If on the in-between months, ask for the days of that month.
        days = yearMonth.lengthOfMonth ();
    } else if ( yearMonth.equals ( stopYm ) ) {  // If on the last of multiple months.
        days = ( int ) ChronoUnit.DAYS.between ( stopYm.atDay ( 1 ).minusDays ( 1 ) , stop ); // Get last day of previous month, to accommodate the `between` method’s use of Half-Open logic.
    } else {
        System.out.println ( "ERROR - Reached impossible point." );
        // FIXME: Handle error condition.
    }
    map.put ( yearMonth , days ); // Cast long to int, auto-boxed to Integer.
    // Prep for next loop.
    yearMonth = yearMonth.plusMonths ( 1 );
} while (  ! yearMonth.isAfter ( stopYm ) );

转储到控制台。

System.out.println ( "start: " + start + " | stop: " + stop + " | map: " + map );

start: 2013-04-17 | stop: 2013-05-21 | map: {2013-04=14, 2013-05=21}