如何在Java 8中一年中每周迭代一次?

mon*_*jbl 6 java java-time

如果我在这里混淆任何ISO日期相关条款,请提前道歉.

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

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

ZonedDateTime date = ZonedDateTime.now();
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int weekNumber = date.get(weekFields.weekOfWeekBasedYear());
Run Code Online (Sandbox Code Playgroud)

鉴于此,我认为必须有可能在Java8 Time API中获取特定年份第一周第一天的日期,但我还没有找到办法.

Tun*_*aki 6

You can construct a date and adjust it to the first day of week for the first week of the year with the following:

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);
Run Code Online (Sandbox Code Playgroud)

Thanks to 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);
Run Code Online (Sandbox Code Playgroud)

WeekFields.ISO represents the ISO definition of the week:

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.

From that definition, you can get:

  • weekBasedYear() represents the week-based-year field:

    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.

    In this case, we want to set it to the wanted year.

  • weekOfWeekBasedYear() represents the week of 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.

    In this case, we want the first week of the week-based-year so we set it to 1.

  • ChronoField.DAY_OF_WEEK which represents the day of the week. In this case, we want the first day of the week so we set to 1.

Then, with such a date, you can indeed iterate over all weeks of the year by calling LocalDate.plusWeeks(1). The question is: how many times do you need to iterate? There can be more than 52 weeks in a year. There are either 52 or 53 weeks in a week-based-year.

You can retrieve the number of weeks with the following. This call rangeRefinedBy(date) to retrieve the valid values of the week of year field for the given date, and get its maximum.

long maxWeekOfYear = weekFields.weekOfWeekBasedYear().rangeRefinedBy(date).getMaximum();
Run Code Online (Sandbox Code Playgroud)