繁体   English   中英

获取 2 个日期之间的周数,周数跨越 2 个月

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM