如何在 Java 8 中遍历一年中的每个星期?

How can I iterate over every week in a year in Java 8?

如果我在这里混淆了任何与 ISO 日期相关的术语,请提前致歉。

我希望能够在给定年份(比如 2015 年)的每个星期进行迭代。我意识到您可以计算 1/1/2015 和 12/31/2015 之间的周数,但这不符合一周的 ISO 标准。相反,它给出了两个日期之间 7 天的天数。一年中的第一个 ISO 周不一定从 1/1/2015 开始。

如果我能得到第一周的第一个日期,我相信我可以简单地通过 ZonedDateTime.plusWeeks(1) 迭代 52 周。您可以通过字段访问器获取任意日期的周数:

ZonedDateTime date = ZonedDateTime.now();
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int weekNumber = date.get(weekFields.weekOfWeekBasedYear());

鉴于此,我认为一定可以在Java8时间[=]中获取特定年的第一周的第一天26=],但我还没有找到办法。

您可以构造一个日期并将其调整为一年中第一周的第一天,方法如下:

int year = 2016;
WeekFields weekFields = WeekFields.ISO;
LocalDate date = LocalDate.now().with(weekFields.weekBasedYear(), year)
                                .with(weekFields.weekOfWeekBasedYear(), 1)
                                .with(ChronoField.DAY_OF_WEEK, 1);

感谢 JodaStephen's comment, another way to put it would be to use the IsoFields class。

LocalDate date = LocalDate.now().with(IsoFields.WEEK_BASED_YEAR, year)
                                .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1)
                                .with(ChronoField.DAY_OF_WEEK, 1);

WeekFields.ISO表示周的ISO定义:

The ISO-8601 definition, where a week starts on Monday and the first week has a minimum of 4 days.

The ISO-8601 standard defines a calendar system based on weeks. It uses the week-based-year and week-of-week-based-year concepts to split up the passage of days instead of the standard year/month/day.

Note that the first week may start in the previous calendar year. Note also that the first few days of a calendar year may be in the week-based-year corresponding to the previous calendar year.

根据该定义,您可以得到:

  • weekBasedYear()代表week-based-year字段:

    This represents the concept of the year where weeks start on a fixed day-of-week, such as Monday and each week belongs to exactly one year.

    在这种情况下,我们要将其设置为想要的年份。

  • weekOfWeekBasedYear()表示week-based-year

    中的星期

    This represents the concept of the count of weeks within the year where weeks start on a fixed day-of-week, such as Monday and each week belongs to exactly one year.

    在这种情况下,我们需要基于周的年份的第一周,因此我们将其设置为 1。

  • ChronoField.DAY_OF_WEEK 表示星期几。在这种情况下,我们想要一周的第一天,所以我们设置为 1。

然后,有了这样一个日期,您确实可以通过调用 LocalDate.plusWeeks(1) 遍历一年中的所有星期。问题是:你需要迭代多少次?一年可能超过 52 周。以周为基础的一年有 52 周或 53 周。

您可以使用以下方法检索周数。此调用 rangeRefinedBy(date) 检索给定日期的一年中的星期字段的有效值,并获取其最大值。

long maxWeekOfYear = weekFields.weekOfWeekBasedYear().rangeRefinedBy(date).getMaximum();