Me gustaría obtener todas las semanas entre 2 fechas con semanas que cruzan 2 meses contadas dos veces por cada mes. Por ejemplo, en 2021, la semana 14 del año acogió marzo y abril, por lo que, en este caso, me gustaría que esa semana se contara dos veces (una para marzo y otra para abril). Busqué y encontré solo bibliotecas que cuentan la cantidad de semanas entre 2 fechas. Creo que podría obtener números de semana y números de mes y formar una matriz única, pero esto parece un poco exagerado. ¿Alguien tiene alguna sugerencia?
Puede obtener el número de semana de esta manera usando java.time:
LocalDate date = LocalDate.of(year, month, day); int weekOfYear = date.get(ChronoField.ALIGNED_WEEK_OF_YEAR);No mencionaste qué versión de Java estás usando. java.time se introdujo en java 8. Hay otras soluciones disponibles para versiones anteriores a java 8.
Con base en lo anterior, debería poder resolver su problema.
semanas que cruzan 2 meses contadas dos veces
El siguiente código permite hacerlo utilizando solo la clase LocalDate estándar y sus métodos isBefore() , plusWeeks() , plusDays() .
Tenga en cuenta que los días de la semana y los meses están representados por java.time .
He hecho un par de suposiciones :
public static void main(String[] args) { System.out.println(getWeekCount(LocalDate.of(2022, 1, 1), LocalDate.of(2022, 2, 1))); System.out.println(getWeekCount(LocalDate.of(2022, 1, 1), LocalDate.of(2022, 3, 1))); } public static int getWeekCount(LocalDate date1, LocalDate date2) { int weekCount = 0; LocalDate cur = date1; LocalDate finish = date2; // assumption: week starts with sunday // assumption: chunk of week at the start and at the end have to be taken into account as well as full weeks if (cur.getDayOfWeek() != DayOfWeek.SUNDAY) { // adjusting current date LocalDate next = cur.plusDays(DayOfWeek.SUNDAY.ordinal() - cur.getDayOfWeek().ordinal() + 1); weekCount += getWeeksIncrement(cur, next); cur = next; } if (finish.getDayOfWeek() != DayOfWeek.SUNDAY) { // adjusting finish date LocalDate previous = finish.minusDays(finish.getDayOfWeek().ordinal() + 1); weekCount += getWeeksIncrement(previous, finish); finish = previous; } while (cur.isBefore(finish) || cur.equals(finish)) { LocalDate next = cur.plusWeeks(1); weekCount += getWeeksIncrement(cur, next); cur = next; } return weekCount; } public static int getWeeksIncrement(LocalDate cur, LocalDate next) { return weekIsSharedBetweenTwoMonth(cur, next) ? 2 : 1; } public static boolean weekIsSharedBetweenTwoMonth(LocalDate cur, LocalDate next) { return next.getMonth() != cur.getMonth() && next.withDayOfMonth(1).isAfter(cur); }Producción
7 - weeks between: 2022-01-01 and 2022-02-01 12 - weeks between: 2022-01-01 and 2022-03-01Bueno, esto se puede lograr con una combinación de la API de fecha y hora de Java ( java.time ) y la API de flujos de Java ( java.util.stream ):
long weeksBetween(LocalDate start, LocalDate endInclusive) { LocalDate normalizedStart = start.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); LocalDate normalizedEndExclusive = endInclusive.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); return Stream.iterate(normalizedStart, d -> d.plusWeeks(1)) .takeWhile(d -> d.isBefore(normalizedEndExclusive)) .mapToInt(d -> d.getMonthValue() == d.plusDays(6).getMonthValue() ? 1 : 2) .sum(); }Lo que sucede aquí, es lo siguiente.
En primer lugar, se normalizan las fechas, es decir, se fijan al inicio de la semana (lunes según las normas ISO).
Luego recorremos el lunes de cada semana y verificamos si su último día de la semana (domingo) se encuentra dentro del mismo mes. Si lo es, entonces da 1 , de lo contrario da 2 .
Finalmente, sumamos todos los valores obtenidos.
Tenga en cuenta que asumí que una semana comienza el lunes (ISO). El código también considera la semana tanto de la fecha de inicio como de la fecha de finalización como completas.