ТЛ; др
LocalDateTime.parse( "2018-08-24T12:18:06,166".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.datesUntil(
LocalDateTime.parse( "2018-08-26T12:19:06,188".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.plusWeeks( 1 )
,
Period.ofWeeks( 1 )
)
.map( localDate -> localDate.get( WeekFields.SUNDAY_START.weekOfWeekBasedYear() ) )
.collect( Collectors.toList() )
.toString()
[34, 35]
Streams
Давайте возьмем идею WeekFields
, показанную в правильный ответ Ole V.V. , но сократим код, используя технологию Java Stream. Хотя это интересно, я не обязательно рекомендую этот подход.
Сначала проанализируйте ваши входные строки, чтобы получить LocalDate
объекты. Класс LocalDate
представляет значение только для даты без времени суток и без часового пояса.
К сожалению, классы java.time не поддерживают запятую как дробный второй разделитель и вместо этого ожидают точку (FULL STOP). Это противоречит стандарту ISO 8601 , который допускает и 1025 * и предпочитает запятую. Это один из немногих недостатков, которые я обнаружил в отличных классах java.time , предположительно из-за предвзятости программистов из Соединенных Штатов. Чтобы обойти этот недостаток, мы заменяем запятую ПОЛНОЙ ОСТАНОВКОЙ.
LocalDate inputDateStart =
LocalDateTime.parse(
"2018-08-24T12:18:06,166".replace( "," , "." ) // Unfortunately, the *java.time* classes fail to support the comma and instead only period. This runs contrary to the ISO 8601 standard which allows both and prefers comma.
)
.toLocalDate()
;
LocalDate inputDateStop =
LocalDateTime.parse(
"2018-08-26T12:19:06,188".replace( "," , "." )
)
.toLocalDate()
;
Вы хотите работать с неделями, определенными как начинающиеся с воскресенья. Поэтому откорректируйте ваши даты ввода до воскресенья или до этой даты.
Обратите внимание, что здесь мы добавляем неделю к остановке, чтобы учесть потребности Вопроса. Чаще мы бы не делали это дополнение, чтобы следовать подходу Half-Open для определения промежутка времени, где начало включительно , а окончание эксклюзив . В отличие от Half-Open, Вопрос, очевидно, требует полностью закрытого подхода, когда начало и конец включаются (я не рекомендую это).
LocalDate start = inputDateStart.with(
TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY )
);
LocalDate stop = inputDateStop.with(
TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY )
)
.plusWeeks( 1 ) // Add one to suit the Question, whereas commonly in date-time work we would have used Half-Open logic.
;
Определить серию дат как Stream< LocalDate >
. Мы прыгаем неделю за раз, пропуская Period
одной недели.
Stream< LocalDate > stream =
startDate
.datesUntil(
stopDate ,
Period.ofWeeks( 1 )
)
;
Если хотите, вы можете увидеть эти даты, собрав их из потока в список. Но обратите внимание, что это истощает поток. Вам нужно будет заново установить поток, чтобы продолжить наш код дальше.
List< LocalDate > dates = stream.collect( Collectors.toList() );
System.out.println( dates );
[2018-08-19, 2018-08-26]
Выполнить эту серию дат в потоке. На каждом объекте LocalDate
получите номер недели. Соберите номер каждой возвращенной недели как Integer
объект, все собранные в List
.
List< Integer > weekNumbers =
stream
.map(
localDate -> localDate.get( WeekFields.SUNDAY_START.weekOfWeekBasedYear() )
)
.collect( Collectors.toList() )
;
Дамп на консоль.
System.out.println( weekNumbers );
[34, 35]
One-лайнер
Если вы действительно хотите сойти с ума от краткости, мы можем сделать все это в одной строке кода. Я не рекомендую это, но это интересно попробовать.
System.out.println(
LocalDateTime.parse( "2018-08-24T12:18:06,166".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.datesUntil(
LocalDateTime.parse( "2018-08-26T12:19:06,188".replace( "," , "." ) ).toLocalDate()
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.plusWeeks( 1 )
,
Period.ofWeeks( 1 )
)
.map( localDate -> localDate.get( WeekFields.SUNDAY_START.weekOfWeekBasedYear() ) )
.collect( Collectors.toList() )
);
[34, 35]