2016-03-22 1 views
5

Извините заранее, если я смущаю любые термины, относящиеся к дате ISO.Как я могу перебирать каждую неделю в году на Java 8?

Я хотел бы иметь возможность перебирать каждую неделю в течение определенного года (скажем, 2015 г.). Я понимаю, что вы можете рассчитать количество недель между 1/1/2015 и 12/31/2015, но это не соответствует стандарту ISO недели. Скорее, он дает количество 7-дневных периодов между двумя датами. Первая неделя ISO года не обязательно начинается 1 января 2012 года.

Если я могу получить первую дату первой недели, я считаю, что могу просто перебрать через ZonedDateTime.plusWeeks(1) на 52 недели. Вы можете получить номер недели в произвольной дат через поле аксессор:

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

Учитывая это, я думаю, что это должно быть возможным, чтобы получить дату первого дня первой недели конкретного год в Java8 Time API, но я еще не нашел способ сделать это.

+0

См. Также [мои примеры] (http://time4j.net/tutorial/appendix.html#x14) для создания даты недели ISO в разных библиотеках. Даже старый JDK с 'java.util.GregorianCalendar', по-видимому, проще, потому что JSR-310 (java.time-package) здесь не имеет простого фабричного метода. –

ответ

4

Вы можете построить дату и настроить его в первый день недели в течение первой недели года со следующим:

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 комментарий, другой способ поставить было бы для использования класса IsoFields.

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 недели:

Определение ISO-8601, где неделя начинается в понедельник и первую неделю имеет минимум 4 дня.

Стандарт ISO-8601 определяет систему календаря на основе недель. Он использует концепции недельного и недельного недель, чтобы разделить количество дней, а не стандартный год/месяц/день.

Обратите внимание, что первая неделя может начаться в предыдущем календарном году. Отметим также, что первые несколько дней календарного года могут быть в недельном году, соответствующем предыдущему календарному году.

Из этого определения, вы можете получить:

  • weekBasedYear() представляет собой поле недели на основе года:

    Это представляет концепцию года, где неделю начать на фиксированном день недели, такой как понедельник и каждую неделю, составляет ровно один год.

    В этом случае мы хотим установить его в желаемый год.

  • weekOfWeekBasedYear() представляет неделю неделю на основе года

    Это представляет концепцию подсчета недель в течение года, где недель начать на фиксированный день-неделю, например, в понедельник и каждый неделя составляет ровно один год.

    В этом случае, мы хотим, чтобы в первой неделе на недельный год поэтому мы устанавливаем его на 1.

  • ChronoField.DAY_OF_WEEK который представляет день недели. В этом случае, мы хотим, чтобы первый день недели, поэтому мы устанавливаем 1.

Затем с такой датой, вы действительно можете перебрать все недели в году по телефону LocalDate.plusWeeks(1). Вопрос в том, сколько раз вам нужно итерации? Это может быть более 52 недель в году. Есть 52 или 53 недели в неделю-год.

Вы можете получить количество недель со следующим. Этот вызов rangeRefinedBy(date) для получения действительных значений поля недели года для данной даты и получения максимального значения.

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

Вам нужны' weekOfWeekBasedYear() 'и' weekBasedYear() ', а не' weekOfYear() 'и' dayOfWeek() '. Они разные. В этом случае, однако, более разумным было бы использовать 'IsoFields.WEEK_OF_WEEK_BASED_YEAR' и' IsoFields.WEEK_BASED_YEAR', что позволило бы избежать путаницы. – JodaStephen

+0

@JodaStephen Не могли бы вы немного расширить? Я тестировал с 2010 по 2020 год, и результат казался правильным, но я допускаю, что иногда имел проблемы со всеми этими определениями :) (и я не знал, что «IsoFields» даже существовал ...). – Tunaki

+1

'weekOfYear()' работает в течение календарного года. 'weekOfWeekBasedYear()' работает в 'weekBasedYear()' (первый день недели за неделю может быть в предыдущем календарном году, а последний день может быть в следующем календарном году). Поскольку ОП спрашивает об ИСО в течение недели, вам нужны методы на основе недели. – JodaStephen