¿Cuál es la mejor manera de recuperar las fechas del último lunes y viernes?

Necesito obtener las fechas para el lunes y el viernes de la semana pasada. Para hacer esto, estoy obteniendo la fecha del lunes de esta semana y restando 7 días. Esto me da la fecha para el lunes de la semana pasada.

Para obtener la fecha del viernes, tengo que agregar 4. Esto me confundió un poco porque, por alguna razón, el primer día de la semana es el domingo, a diferencia del lunes aquí en el Reino Unido.

De todos modos, aquí es cómo estoy obteniendo las fechas.

// Get the dates for last MON & FRI Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); cal.add(Calendar.DAY_OF_WEEK, -7); cal.set(Calendar.HOUR_OF_DAY,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); // Get the date on Friday cal.add(Calendar.DAY_OF_WEEK, 4); cal.set(Calendar.HOUR_OF_DAY,23); cal.set(Calendar.MINUTE,59); cal.set(Calendar.SECOND,59); cal.set(Calendar.MILLISECOND,0); 

Lo anterior funciona, pero me interesa si hay algún problema con la lógica. Por ejemplo, funcionará en febrero, años bisiestos, etc.

Siéntase libre de sugerir una mejor solución / enfoque.

Gracias

Nota: Para Java 8 y superior, eche un vistazo a la respuesta de Basil Bourque ( enlace ).
Java 8 introdujo una nueva API de fecha / hora que ofrece la mayor parte de la funcionalidad de Joda-Time.


Joda-Time ofrece métodos realmente buenos para problemas como ese.

Obtener las fechas para el lunes y el viernes de la semana pasada sería algo como esto usando Joda Time:

 DateTime today = DateTime.now(); DateTime sameDayLastWeek = today.minusWeeks(1); DateTime mondayLastWeek = sameDayLastWeek.withDayOfWeek(DateTimeConstants.MONDAY); DateTime fridayLastWeek = sameDayLastWeek.withDayOfWeek(DateTimeConstants.FRIDAY); 

Puede crear objetos DateTime partir de objetos java.util.Date y viceversa para que sea fácil de usar con fechas Java.


Usando el código anterior con la fecha.

 DateTime today = new DateTime("2012-09-30"); 

da como resultado “2012-09-17” para el lunes y “2012-09-21” para el viernes, estableciendo la fecha en

 DateTime tomorrow = new DateTime("2012-10-01"); 

resultados en “2012-09-24” para el lunes y “2012-09-28” para el viernes.

tl; dr

Obtén las fechas para el lunes y viernes de la semana pasada.

 LocalDate previousMonday = LocalDate.now( ZoneId.of( "America/Montreal" ) ) .with( TemporalAdjusters.previous( DayOfWeek.MONDAY ) ) ; 

Evitar las clases de fecha y hora heredadas

Las otras Respuestas utilizan las antiguas y problemáticas clases de fecha y hora que ahora están suplantadas por las preguntas java.time.

LocalDate

La clase LocalDate representa un valor de solo fecha sin hora del día y sin zona horaria.

Una zona horaria es crucial para determinar una fecha. Para un momento dado, la fecha varía alrededor del mundo por zona. Por ejemplo, unos pocos minutos después de la medianoche en París, Francia es un nuevo día, mientras que todavía es “ayer” en Montreal Québec .

 ZoneId z = ZoneId.of( “America/Montreal” ); LocalDate today = LocalDate.now( z ); 

TemporalAdjuster

La interfaz TemporalAdjuster permite que los ajustes se muevan de un valor de fecha-hora a otro. Encuentre implementaciones útiles en la clase TemporalAdjusters (note el plural ‘s’). El ajustador previous encuentra cualquier objeto especificado de la enumeración DayOfWeek .

La pregunta no define exactamente “la semana pasada”. Últimos siete días? ¿Período estándar de lunes a domingo? ¿Semana localizada, como domingo a sábado en los Estados Unidos? ¿La semana anterior a la semana de hoy o incluyendo la semana parcial de hoy?

Asumiré que los siete días anteriores fueron previstos.

 LocalDate previousMonday = today.with( TemporalAdjusters.previous( DayOfWeek.MONDAY ) ) ; LocalDate previousFriday = today.with( TemporalAdjusters.previous( DayOfWeek.FRIDAY ) ) ; 

Por cierto, si desea considerar la fecha inicial si ya es el día de la semana deseado, use implementaciones alternativas de nextOrSame : previousOrSame o nextOrSame .


Acerca de java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases sustituyen a las antiguas y problemáticas clases de fecha y hora como java.util.Date , Calendar y SimpleDateFormat .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Para obtener más información, consulte el Tutorial de Oracle . Y busca Stack Overflow para muchos ejemplos y explicaciones. La especificación es JSR 310 .

Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No se necesitan cadenas, no se necesitan clases java.sql.* .

¿Dónde obtener las clases java.time?

  • Java SE 8 , Java SE 9 y posteriores
    • Incorporado.
    • Parte de la API de Java estándar con una implementación en paquete.
    • Java 9 agrega algunas características menores y correcciones.
  • Java SE 6 y Java SE 7
    • Gran parte de la funcionalidad de java.time está respaldada a Java 6 y 7 en ThreeTen-Backport .
  • Androide
    • Versiones posteriores de las implementaciones de paquetes de Android de las clases java.time.
    • Para Android anterior (<26), el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Vea Cómo usar ThreeTenABP… .

El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí como Interval , YearWeek , YearQuarter , y más .

Todavía tiene el inicio de la semana progtwigdo para el domingo, lo que significa que Calendar.MONDAY en sábado es el lunes anterior, mientras que Calendar.MONDAY en domingo es el día siguiente.

Lo que debe hacer es (de acuerdo a cómo lo desee de acuerdo con su comentario anterior), establecer el comienzo de la semana para el lunes.

 Calendar cal = Calendar.getInstance(); cal.setFirstDayOfWeek(Calendar.MONDAY); cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); cal.add(Calendar.DAY_OF_WEEK, -7); ... 

Más allá de eso, y como el último segundo del viernes no está incluido en el rango, su lógica parece sólida, y no debería tener problemas con los años bisiestos / cambios de horario de verano, etc.

Lo único que veo mal es que, de hecho, está probando el rango Mo-Fr, y no, como se dijo, recuperando dos días específicos. Sería más seguro probar el rango Mo-Sa con un límite superior exclusivo.