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

发布于 2025-01-11 04:20:15 字数 174 浏览 0 评论 0原文

我想得到两个日期之间的所有周,并且每个月计算两次跨越两个月的周。例如,2021 年的第 14 周同时举办了 3 月和 4 月,因此在这种情况下,我希望该周计算两次(一次为 3 月,一次为 4 月)。我查看并发现只有一些库可以计算两个日期之间的周数。我想我可以得到周数和月份数并形成一个独特的数组,但这似乎有点过头了。有人有什么建议吗?

I would like to get all the weeks between 2 dates with weeks that cross 2 months counted twice for each month. 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). 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

剪不断理还乱 2025-01-18 04:20:15

跨 2 个月的周计算两次

下面的代码允许仅使用标准 LocalDate 类及其方法 isBefore()plusWeeks(),<代码>plusDays()。

请记住,星期几月份java.time包中的枚举表示。

我做了几个假设

  • 一周从星期日开始;
  • 必须考虑给定期间开始结束的一周中的大部分时间以及完整的周。
    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);
    }

输出

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

weeks that cross 2 months counted twice

The code below allows to do that by utilizing only the standard LocalDate class and it's methods isBefore(), plusWeeks(), plusDays().

Keep in mind the days of the week and months are represented by enums from the 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

7   -  weeks between: 2022-01-01 and 2022-02-01
12  -  weeks between: 2022-01-01 and 2022-03-01
柒夜笙歌凉 2025-01-18 04:20:15

好吧,这可以通过 Java 日期和时间 API (java.time) 和 Java Streams 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)。该代码还将开始日期和结束日期所在的星期视为完整日期。

Well, this is achievable with a combination of the Java Date and Time API (java.time) and the Java Streams 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).

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.

At last, we sum all yielded values.


Note that I assumed that a week starts on Monday (ISO). The code also considers the week of both the start date as the end date as full ones.

百思不得你姐 2025-01-18 04:20:15

您可以使用 java.time 获取这样的周数:

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

您没有提及您正在使用哪个 java 版本。 java.time是在java 8中引入的。对于java 8之前的版本还有其他可用的解决方案。

基于上述,您应该能够解决您的问题。

You can get the weeknumber like this using 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.time was introduced in java 8. There are other solutions available for pre-java 8.

Based on the above, you should be able to solve your problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文