简体   繁体   English

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

[英]Get weeks between 2 dates with weeks crossing 2 months

I would like to get all the weeks between 2 dates with weeks that cross 2 months counted twice for each month.我想得到 2 个日期之间的所有星期,每个月计算两次跨越 2 个月的星期。 For example, in 2021 week 14 of the year hosted both March and April so in this case, I would like that week counted twice (once for March and once for April).例如,在 2021 年的第 14 周同时举办了 3 月和 4 月,因此在这种情况下,我希望该周计算两次(一次用于 3 月,一次用于 4 月)。 I've looked and found just libraries that count the number of weeks between 2 dates.我查看并找到了计算两个日期之间的周数的库。 I think I could get week numbers and month numbers and form a unique array but this seems a bit over the top.我想我可以获得周数和月份数并形成一个独特的数组,但这似乎有点过头了。 Has anyone got any suggestions?有人有什么建议吗?

weeks that cross 2 months counted twice跨越 2 个月的周算了两次

The code below allows to do that by utilizing only the standard LocalDate class and it's methods isBefore() , plusWeeks() , plusDays() .下面的代码允许仅使用标准LocalDate class 及其方法isBefore()plusWeeks()plusDays()来做到这一点。

Keep in mind the days of the week and months are represented by enums from the java.time package.请记住,星期几月份java.time package 中的枚举表示。

I've made a couple of assumptions :我做了几个假设

  • week starts with Sunday ;星期从星期日开始;
  • chunks of the week at the start and at the end of the given period have to be taken into account as well as full-length weeks.必须考虑给定时间段开始结束时的一周时间段以及完整的周数。
    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 Output

7   -  weeks between: 2022-01-01 and 2022-02-01
12  -  weeks between: 2022-01-01 and 2022-03-01

Well, this is achievable with a combination of the Java Date and Time API ( java.time ) and the Java Streams API ( java.util.stream ):好吧,这可以通过结合使用 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();
}

What happens here, is as follows.这里发生的事情如下。

First, the dates are normalized , that is, they are set to the start of the week (Monday according to ISO standards).首先,日期被规范化,也就是说,它们被设置为一周的开始(根据 ISO 标准是星期一)。

Then we walk over the Monday of each week, and check if its last day of the week (Sunday) lies within the same month.然后我们遍历每个星期的星期一,并检查它的最后一天(星期日)是否在同一个月内。 If it is, then it yields 1 , otherwise it yields 2 .如果是,则产生1 ,否则产生2

At last, we sum all yielded values.最后,我们对所有产生的值求和。


Note that I assumed that a week starts on Monday (ISO).请注意,我假设一周从星期一 (ISO) 开始。 The code also considers the week of both the start date as the end date as full ones.该代码还将开始日期和结束日期的一周视为完整日期。

You can get the weeknumber like this using java.time:您可以使用 java.time 获取周数:

LocalDate date = LocalDate.of(year, month, day);
int weekOfYear = date.get(ChronoField.ALIGNED_WEEK_OF_YEAR);

You did not mention which java version you are using.您没有提到您使用的是哪个 java 版本。 java.time was introduced in java 8. There are other solutions available for pre-java 8. java.time 是在 java 8 中引入的。还有其他解决方案可用于 pre-java 8。

Based on the above, you should be able to solve your problem.基于以上,你应该能够解决你的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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