Для группировки по номеру недели следует использовать класс WeekFields
из Java Date/Time API (см. ответ на похожий вопрос: Как сгруппировать строки по неделям, месяцам и кварталам?).
Однако здесь следует точно определить, как именно будет вычисляться номер недели, так как это зависит от дня начала недели -- два самых известных подхода воскресенье или понедельник, и минимального количества дней, которые должны быть в неделе.
Если дней в первой неделе меньше минимума, то она будет считаться как 52 неделя прошлого года для метода WeekFields::weekOfWeekBasedYear
или 0 для WeekFields::weekOfYear
.
Таким образом, для выполнения группировки можно определить метод вроде такого, чтобы можно было передать ссылку на любой из вышеуказанных методов:
public static Map<Integer, Integer> datesByWeek(Supplier<TemporalField> weekField, List<String> dates) {
return dates.stream()
.collect(Collectors.groupingBy(
d -> LocalDate.parse(d).get(weekField.get()),
LinkedHashMap::new, // поддержать порядок вставки
Collectors.summingInt(d -> 1)
));
}
Тест для разных экземпляров WeekFields
c первым и последним днём года:
var dates = Arrays.asList("2022-01-01", "2022-07-20", "2022-07-25", "2022-07-26", "2022-12-31");
Supplier<TemporalField> weekFields = WeekFields.of(DayOfWeek.MONDAY, 1)::weekOfWeekBasedYear;
var byWeekMon = datesByWeek(weekFields, dates);
System.out.println("MON: " + byWeekMon);
var byWeekSun = datesByWeek(WeekFields.SUNDAY_START::weekOfYear, dates);
System.out.println("SUN: " + byWeekSun);
var byWeekIso = datesByWeek(WeekFields.ISO::weekOfYear, dates);
System.out.println("ISO: " + byWeekIso);
Результаты:
MON: {1=2, 30=1, 31=2} // номер недели 1 для начала и конца года
SUN: {1=1, 30=1, 31=2, 53=1}
ISO: {0=1, 29=1, 30=2, 52=1}
Кстати, ни по одному календарю не выходит, что 25 и 26 июля 2022 года пришлись на 29 неделю.
