Saltar al contenido

Cómo calcular la fecha del número de semana ISO8601 en Java

Te doy la bienvenida a proyecto online, en este lugar hallarás la solucíon a lo que buscabas.

Solución:

ACTUALIZACIÓN: Los conceptos presentados aquí aún se aplican, pero el código está obsoleto. El proyecto Joda-Time, ahora en modo de mantenimiento, aconseja la migración a las clases java.time. Vea el código java.time en la Respuesta de Szulc.

Respuesta corta

DateTime dateTimeStart = new DateTime( "2003-W01-1", DateTimeZone.UTC ); // Joda-Time 2.4.
DateTime dateTimeStop = dateTimeStart.plusWeeks( 1 );

Para más detalles, sigue leyendo.

Evitar juDate

Las antiguas clases java.util.Date y java.util.Calendar incluidas con Java son notoriamente problemáticas y deben evitarse. Sun y sus socios pusieron muchas cosas buenas en las bibliotecas de Java, pero no todas son buenas. Las clases de fecha y hora son quizás lo peor.

Además, esas clases tienen un soporte débil para las semanas ISO 8601. Vea esta respuesta para más detalles.

Reglas de la Semana ISO

Podrías escribir tu propio código usando esas clases, pero no lo recomiendo. Las reglas para el cálculo de las semanas ISO son bastante simples:

  • La semana 1 tiene el primer jueves del año calendario.
  • El lunes es el primer día de la semana.

Joda-Tiempo

En su lugar, el reemplazo común es una biblioteca llamada Joda-Time. Esta biblioteca incluye un excelente soporte para las semanas ISO.

Fácil de agregar a su proyecto, solo agregue un solo .jar expediente.

Otro código de ejemplo

Vea esta otra respuesta mía o esta como código de ejemplo para obtener una fecha y hora de un número de semana ISO.

java.tiempo

Java 8 tiene un nuevo marco de fecha y hora, inspirado en Joda-Time, que se encuentra en el java.time paquete.

Agregar bibliotecas

Java está diseñado para mezclar bibliotecas. Hacerlo es uno de los propósitos principales de la programación orientada a objetos y el enlace tardío. Los comentarios sobre su pregunta se refieren a la situación demasiado común en la que los jefes, irracionalmente o por ignorancia, prohíben agregar bibliotecas. Si bien existen razones válidas para tal prohibición, son raras.

Prohibir agregar bibliotecas y jars en Java es como prohibir enganchar remolques en una flota de vehículos equipados con un enganche.

Las viejas clases de fecha y hora son lo suficientemente malas como para que muchos de nosotros agreguemos Joda-Time a la mayoría de los proyectos nuevos como un hábito.

Medio abierto

En el trabajo de fecha y hora, una forma común de definir un lapso de tiempo es el enfoque “Medio abierto”. Esto significa que el comienzo es inclusivo mientras que el final es exclusivo. Entonces, una semana estándar comienza en el primer momento de un lunes y termina en el primer momento del lunes siguiente. Busque StackOverflow.com para obtener más información y ejemplos.

Diagrama del enfoque semiabierto para definir una semana, desde el inicio del día 1 hasta el inicio del día 8

Representación textual de la Semana ISO

El estándar ISO 8601 define formas de representar una semana estándar e incluso un día dentro de esa semana.

Tome el año, un guión, un W delimitador, y el número de semana representa la semana completa: YYYY-Www. Agregue un guión y un número de día de la semana para identificar un día dentro de esa semana: YYYY-Www-D.

Joda-Time entiende este formato como se ve en el ejemplo de código a continuación.

Código de ejemplo

Aquí hay un código Joda-Time 2.4. Busque en StackOverflow.com para ver discusiones y ejemplos de estos conceptos. Esta pregunta y esta respuesta prácticamente duplican muchas otras.

int year = 2003;
int week = 1; // Domain: 1 to 53.

// Build a String in ISO 8601 Week format: YYYY-Www-D
// Hard-coding a `1` for Monday, the standard first-day-of-week.
String input = ( String.format( "%04d", year ) + "-W" + String.format( "%02d", week ) + "-1" );

// Specify the time zone by which to define the beginning of a day.
DateTimeZone timeZone = DateTimeZone.UTC; // Or: DateTimeZone.forID( "America/Montreal" );

// Calculate beginning and ending, using Half-Open (inclusive, exclusive) approach.
DateTime dateTimeStart = new DateTime( input, timeZone );
DateTime dateTimeStop = dateTimeStart.plusWeeks( 1 );

// Use Joda-Time's tidy Interval class to represent the entire week. Use getters to access start and stop.
Interval weekInterval = new Interval( dateTimeStart, dateTimeStop );

// Is today in that week? Joda-Time has handy methods: contains, isBefore, isAfter, overlap.
boolean isTodayInThatWeek = weekInterval.contains( DateTime.now() );

Volcar a la consola.

System.out.println( "input: " + input );
System.out.println( "dateTimeStart: " + dateTimeStart );
System.out.println( "dateTimeStop: " + dateTimeStop );
System.out.println( "interval: " + interval );
System.out.println( "isTodayInThatWeek: " + isTodayInThatWeek );

Cuando se ejecuta.

input: 2003-W01-1
dateTimeStart: 2002-12-30T00:00:00.000Z
dateTimeStop: 2003-01-06T00:00:00.000Z
interval: 2002-12-30T00:00:00.000Z/2003-01-06T00:00:00.000Z
isTodayInThatWeek: false

La forma de Java 8 / java.time

En Java 8, puede usar Campo temporal combinado con LocalDate::with(TemporalField, largo) método para obtener la semana correcta (del año basado en la semana) y Ajustador Temporal combinado con LocalDate::with(TemporalAdjuster) método para saltar al día requerido de la semana, así:

final int year = 2020;
final int weekNumber = 34;

LocalDate mondayOfWeek = LocalDate.of(year, Month.JUNE, 1)
                         .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)
                         .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));

LocalDate sundayOfWeek = mondayOfWeek.plusDays(6);

LocalDate date = 
  LocalDate.parse("2015 53", 
     new DateTimeFormatterBuilder().appendPattern("YYYY w")
    .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
    .toFormatter()));

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *