¿Cómo verifico si una fecha está dentro de un rango determinado?

Resuelto Mike Sickler asked hace 15 años • 17 respuestas

Tengo una serie de rangos con fechas de inicio y fechas de finalización. Quiero comprobar si una fecha está dentro de ese rango.

Date.before() y Date.after() parecen un poco incómodos de usar. Lo que realmente necesito es algo como este pseudocódigo:

boolean isWithinRange(Date testDate) {
    return testDate >= startDate && testDate <= endDate;
}

No estoy seguro de si es relevante, pero las fechas que extraigo de la base de datos tienen marcas de tiempo.

Mike Sickler avatar Jan 30 '09 08:01 Mike Sickler
Aceptado
boolean isWithinRange(Date testDate) {
   return !(testDate.before(startDate) || testDate.after(endDate));
}

No me parece tan incómodo. Tenga en cuenta que lo escribí de esa manera en lugar de

return testDate.after(startDate) && testDate.before(endDate);

por lo que funcionaría incluso si testDate fuera exactamente igual a uno de los casos finales.

Paul Tomblin avatar Jan 30 '2009 01:01 Paul Tomblin

tl; dr

ZoneId z = ZoneId.of( "America/Montreal" );  // A date only has meaning within a specific time zone. At any given moment, the date varies around the globe by zone.
LocalDate ld = 
    givenJavaUtilDate.toInstant()  // Convert from legacy class `Date` to modern class `Instant` using new methods added to old classes.
                     .atZone( z )  // Adjust into the time zone in order to determine date.
                     .toLocalDate();  // Extract date-only value.

LocalDate today = LocalDate.now( z );  // Get today’s date for specific time zone.
LocalDate kwanzaaStart = today.withMonth( Month.DECEMBER ).withDayOfMonth( 26 );  // Kwanzaa starts on Boxing Day, day after Christmas.
LocalDate kwanzaaStop = kwanzaaStart.plusWeeks( 1 );  // Kwanzaa lasts one week.
Boolean isDateInKwanzaaThisYear = (
    ( ! today.isBefore( kwanzaaStart ) ) // Short way to say "is equal to or is after".
    &&
    today.isBefore( kwanzaaStop )  // Half-Open span of time, beginning inclusive, ending is *exclusive*.
)

Medio abierto

El trabajo de fecha y hora suele emplear el enfoque "medio abierto" para definir un lapso de tiempo. El comienzo es inclusivo mientras que el final es exclusivo . Por lo tanto, una semana que comienza un lunes dura hasta el lunes siguiente, pero no lo incluye.

java.tiempo

Java 8 y posteriores vienen con el java.timemarco integrado. Reemplaza las antiguas y problemáticas clases incluidas java.util.Date/.Calendary SimpleDateFormat. Inspirado en la exitosa biblioteca Joda-Time. Definido por JSR 310. Ampliado por el proyecto ThreeTen-Extra.

An Instantes un momento en la línea de tiempo en UTC con una resolución de nanosegundos.

Instant

Convierte tus java.util.Dateobjetos en objetos instantáneos.

Instant start = myJUDateStart.toInstant();
Instant stop =

Si obtiene java.sql.Timestampobjetos a través de JDBC desde una base de datos, conviértalos a java.time.Instant de manera similar. A java.sql.Timestampya está en UTC, por lo que no hay necesidad de preocuparse por las zonas horarias.

Instant start = mySqlTimestamp.toInstant() ;
Instant stop =

Obtenga el momento actual para comparar.

Instant now = Instant.now();

Compare usando los métodos isBefore, isAfter y es igual.

Boolean containsNow = ( ! now.isBefore( start ) ) && ( now.isBefore( stop ) ) ;

LocalDate

Quizás desee trabajar sólo con la fecha, no con la hora del día.

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

LocalDate start = LocalDate.of( 2016 , 1 , 1 ) ;
LocalDate stop = LocalDate.of( 2016 , 1 , 23 ) ;

Para obtener la fecha actual, especifique una zona horaria. En cualquier momento dado, la fecha de hoy varía según la zona horaria. Por ejemplo, un nuevo día amanece más temprano en París que en Montreal.

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );

Podemos usar los métodos isEqual, isBeforey isAfterpara comparar. En el trabajo de citas y horas, comúnmente utilizamos el enfoque semiabierto donde el comienzo de un lapso de tiempo es inclusivo mientras que el final es exclusivo .

Boolean containsToday = ( ! today.isBefore( start ) ) && ( today.isBefore( stop ) ) ;

Interval

Si elige agregar la biblioteca ThreeTen-Extra a su proyecto, puede usar la Intervalclase para definir un lapso de tiempo. Esa clase ofrece métodos para probar si el intervalo contiene , linda , encierra o se superpone a otras fechas/intervalos.

La Intervalclase trabaja con Instantobjetos. La Instantclase representa un momento en la línea de tiempo en UTC con una resolución de nanosegundos (hasta nueve (9) dígitos de una fracción decimal).

Podemos ajustarlo LocalDatea un momento concreto, el primer momento del día, especificando una zona horaria para obtener un ZonedDateTime. Desde allí podemos volver a UTC extrayendo un archivo Instant.

ZoneId z = ZoneId.of( "America/Montreal" );
Interval interval = 
    Interval.of( 
        start.atStartOfDay( z ).toInstant() , 
        stop.atStartOfDay( z ).toInstant() );
Instant now = Instant.now();
Boolean containsNow = interval.contains( now );

Acerca de java.time

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

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

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

¿ Dónde obtener las java.timeclases?

  • Java SE 8 y SE 9 y posteriores
  • Incorporado.
  • Parte de la API de Java estándar con una implementación incluida.
  • Java 9 agrega algunas características y correcciones menores.
  • Java SE 6 y SE 7
  • Gran parte de la java.timefuncionalidad está adaptada a Java 6 y 7 en ThreeTen-Backport .
  • Androide
  • El proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente) específicamente para Android.
  • Consulte Cómo utilizar… .

El proyecto ThreeTen-Extrajava.time se amplía con clases adicionales. Este proyecto es un campo de pruebas para posibles futuras incorporaciones a java.time. Puede encontrar algunas clases útiles aquí, como , Interval, y más .YearWeekYearQuarter

Basil Bourque avatar Feb 09 '2016 19:02 Basil Bourque

Esa es la forma correcta. Los calendarios funcionan de la misma manera. Lo mejor que puedo ofrecerle (según su ejemplo) es esto:

boolean isWithinRange(Date testDate) {
    return testDate.getTime() >= startDate.getTime() &&
             testDate.getTime() <= endDate.getTime();
}

Date.getTime() devuelve el número de milisegundos desde el 1/1/1970 a las 00:00:00 GMT, y es largo, por lo que es fácilmente comparable.

MBCook avatar Jan 30 '2009 01:01 MBCook

Considere usar Joda Time . Me encanta esta biblioteca y desearía que reemplazara el horrible desastre actual que son las clases Java Date y Calendar existentes. Es un manejo de fechas bien hecho.

EDITAR: Ya no estamos en 2009 y Java 8 lleva años disponible. Utilice las clases java.time integradas de Java 8 que se basan en Joda Time, como menciona Basil Bourque anteriormente. En este caso querrás la clase Period, y aquí tienes el tutorial de Oracle sobre cómo usarla.

Ben Hardy avatar Jan 30 '2009 01:01 Ben Hardy