簡體   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