[英]Get weeks between 2 dates with weeks crossing 2 months
我想得到 2 个日期之间的所有星期,每个月计算两次跨越 2 个月的星期。 例如,在 2021 年的第 14 周同时举办了 3 月和 4 月,因此在这种情况下,我希望该周计算两次(一次用于 3 月,一次用于 4 月)。 我查看并找到了计算两个日期之间的周数的库。 我想我可以获得周数和月份数并形成一个独特的数组,但这似乎有点过头了。 有人有什么建议吗?
跨越 2 个月的周算了两次
下面的代码允许仅使用标准LocalDate
class 及其方法isBefore()
、 plusWeeks()
、 plusDays()
来做到这一点。
请记住,星期几和月份由java.time
package 中的枚举表示。
我做了几个假设:
public static void main(String[] args) {
System.out.println(getWeekCount(LocalDate.of(2022, 1, 1),
LocalDate.of(2022, 2, 1)));
System.out.println(getWeekCount(LocalDate.of(2022, 1, 1),
LocalDate.of(2022, 3, 1)));
}
public static int getWeekCount(LocalDate date1, LocalDate date2) {
int weekCount = 0;
LocalDate cur = date1;
LocalDate finish = date2;
// assumption: week starts with sunday
// assumption: chunk of week at the start and at the end have to be taken into account as well as full weeks
if (cur.getDayOfWeek() != DayOfWeek.SUNDAY) { // adjusting current date
LocalDate next = cur.plusDays(DayOfWeek.SUNDAY.ordinal() - cur.getDayOfWeek().ordinal() + 1);
weekCount += getWeeksIncrement(cur, next);
cur = next;
}
if (finish.getDayOfWeek() != DayOfWeek.SUNDAY) { // adjusting finish date
LocalDate previous = finish.minusDays(finish.getDayOfWeek().ordinal() + 1);
weekCount += getWeeksIncrement(previous, finish);
finish = previous;
}
while (cur.isBefore(finish) || cur.equals(finish)) {
LocalDate next = cur.plusWeeks(1);
weekCount += getWeeksIncrement(cur, next);
cur = next;
}
return weekCount;
}
public static int getWeeksIncrement(LocalDate cur, LocalDate next) {
return weekIsSharedBetweenTwoMonth(cur, next) ? 2 : 1;
}
public static boolean weekIsSharedBetweenTwoMonth(LocalDate cur, LocalDate next) {
return next.getMonth() != cur.getMonth() &&
next.withDayOfMonth(1).isAfter(cur);
}
Output
7 - weeks between: 2022-01-01 and 2022-02-01
12 - weeks between: 2022-01-01 and 2022-03-01
好吧,这可以通过结合使用 Java 日期和时间 API ( java.time
) 和 Java 流 API ( java.util.stream
) 来实现:
long weeksBetween(LocalDate start, LocalDate endInclusive) {
LocalDate normalizedStart = start.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
LocalDate normalizedEndExclusive = endInclusive.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
return Stream.iterate(normalizedStart, d -> d.plusWeeks(1))
.takeWhile(d -> d.isBefore(normalizedEndExclusive))
.mapToInt(d -> d.getMonthValue() == d.plusDays(6).getMonthValue() ? 1 : 2)
.sum();
}
这里发生的事情如下。
首先,日期被规范化,也就是说,它们被设置为一周的开始(根据 ISO 标准是星期一)。
然后我们遍历每个星期的星期一,并检查它的最后一天(星期日)是否在同一个月内。 如果是,则产生1
,否则产生2
。
最后,我们对所有产生的值求和。
请注意,我假设一周从星期一 (ISO) 开始。 该代码还将开始日期和结束日期的一周视为完整日期。
您可以使用 java.time 获取周数:
LocalDate date = LocalDate.of(year, month, day);
int weekOfYear = date.get(ChronoField.ALIGNED_WEEK_OF_YEAR);
您没有提到您使用的是哪个 java 版本。 java.time 是在 java 8 中引入的。还有其他解决方案可用于 pre-java 8。
基于以上,你应该能够解决你的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.