收集一段时间内每个月的天数
Collect the number of days per month in each month in a span of time
我被困在这几天我搜索了很多,我在 java swing 程序中使用 jodatime 库
所以这就是我需要的
从 2013-04-17 到 2013-05-21
我需要这样输出结果:
- 2013 年 4 月(天数 = 14)
- 5 月 2013(天数 = 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}
我被困在这几天我搜索了很多,我在 java swing 程序中使用 jodatime 库 所以这就是我需要的 从 2013-04-17 到 2013-05-21 我需要这样输出结果:
- 2013 年 4 月(天数 = 14)
- 5 月 2013(天数 = 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}