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

8 minutos de lectura

avatar de usuario
mike hoz

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

Date.before() y Date.after() parecen ser 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.

  • Pregunta similar con múltiples respuestas: ¿Cómo puedo determinar si una fecha está entre dos fechas en Java?

    – Basil Bourque

    9 de febrero de 2016 a las 18:47


  • FYI, las viejas y problemáticas clases de fecha y hora como java.util.Date y java.util.Calendar son ahora legadosuplantado por el java.tiempo clases Ver Tutorial de Oracle.

    – Basil Bourque

    4 sep 2017 a las 22:56


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.

  • con este código lo siguiente no es válido: date is 01-01-2014 and the range is from 01-01-2014 to 31-01-2014 ¿Cómo puedes hacer que sea válido?

    – Shahe

    31 de enero de 2014 a las 9:36


  • @Shahe, lo primero que haría es verificar las porciones de tiempo de sus fechas. Las posibilidades son tu date es temprano en la mañana y startDate está detrás de eso.

    –Paul Tomblin

    31 de enero de 2014 a las 13:20

  • este truco de negar o sigue siendo agradable después de siete años. : )

    – Tosz

    16/09/2016 a las 11:33

  • No funciona cuando testDate es la fecha actual de hoy. Cómo manejar este escenario en la solución sugerida anteriormente.

    – Rápido

    8 de diciembre de 2016 a las 12:14

  • @Rápido Date contiene tiempo (horas, minutos, segundos y milisegundos). Entonces, si desea probar si algo es “hoy”, debe crear un objeto Fecha que sea “hoy” a las 0:00:00.000 y uno que sea “mañana” a las 0:00:00.000. Yo uso el Calendar class para eso, pero estoy seguro de que hay una mejor manera si usa JodaTime o las clases Java base más nuevas.

    –Paul Tomblin

    08/12/2016 a las 15:35

avatar de usuario
albahaca bourque

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 comúnmente emplea el enfoque “Medio abierto” para definir un lapso de tiempo. el principio es inclusivo mientras que el final es exclusivo. Entonces, una semana que comienza un lunes termina, pero no incluye, el lunes siguiente.

java.tiempo

Java 8 y posteriores vienen con el java.time marco incorporado. Reemplaza las viejas clases problemáticas que incluyen java.util.Date/.Calendar y SimpleDateFormat. Inspirado en la exitosa biblioteca Joda-Time. Definido por JSR 310. Extendido por el proyecto ThreeTen-Extra.

Un Instant es un momento en la línea de tiempo en UTC con resolución de nanosegundos.

Instant

Convierte tu java.util.Date objetos a objetos instantáneos.

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

si conseguir java.sql.Timestamp objetos a través de JDBC desde una base de datos, convertir a java.time.Instant en una manera similar. UN java.sql.Timestamp ya está en UTC, por lo que no debe preocuparse por las zonas horarias.

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

Obtenga el momento actual para comparar.

Instant now = Instant.now();

Compare utilizando los métodos isBefore, isAfter y equals.

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

LocalDate

Tal vez quiera trabajar solo con la fecha, no con la hora del día.

Él LocalDate class 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 antes en París que en Montreal.

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

Podemos usar el isEqual, isBeforey isAfter Métodos para comparar. En el trabajo de fecha y hora, comúnmente usamos 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 opta por agregar el ThreeTen-Extra biblioteca a su proyecto, puede usar el Interval clase para definir un lapso de tiempo. Esa clase ofrece métodos para probar si el intervalo contiene, linda, encierrao se superpone otras fechas-horas/intervalos.

Él Interval la clase trabaja en Instant objetos. Él Instant clase representa un momento en la línea de tiempo en UTC con resolución de nanosegundos (hasta nueve (9) dígitos de una fracción decimal).

Podemos ajustar el LocalDate en un momento específico, el primer momento del día, especificando una zona horaria para obtener un ZonedDateTime. Desde allí podemos volver a UTC extrayendo un 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

Él java.tiempo framework está integrado en Java 8 y versiones posteriores. Estas clases suplantan a las viejas y problemáticas legado clases de fecha y hora como java.util.Date, Calendar& SimpleDateFormat.

Él Joda-Tiempo proyecto, ahora en modo de mantenimientoaconseja la migración a la java.time clases

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

Dónde obtener el java.time clases?

  • Java SE 8 y SE 9 y después
  • Incorporado.
  • Parte de la API de Java estándar con una implementación integrada.
  • Java 9 agrega algunas características y correcciones menores.
  • Java SE 6 y SE 7
  • Mucho de java.time la funcionalidad está adaptada a Java 6 y 7 en ThreeTen-Backport.
  • Androide
  • Él TresDiezABP el proyecto se adapta ThreeTen-Backport (mencionado anteriormente) para Android específicamente.
  • Ver Cómo utilizar….

Él ThreeTen-Extra el proyecto se extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles futuras adiciones a java.time. Puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuartery más.

Esa es la forma correcta. Los calendarios funcionan de la misma manera. Lo mejor que podría ofrecerle (basado en 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.

avatar de usuario
Ben Hardy

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

EDITAR: ya no es 2009, y Java 8 ha estado fuera durante mucho tiempo. Utilice las clases java.time integradas de Java 8 que se basan en Joda Time, como menciona anteriormente Basil Bourque. En este caso, querrá la clase Período, y aquí está tutorial de oracle sobre cómo usarlo.

Una manera fácil es convertir las fechas en milisegundos después del 1 de enero de 1970 (use Date.getTime()) y luego compare estos valores.

avatar de usuario
epoxi

Ya que Java 8

NOTA: Todos menos uno DateLos constructores están en desuso. La mayoría de DateLos métodos de están en desuso. ÁRBITRO: Fecha: métodos obsoletos. Todo pero Date::from(Instant)los métodos estáticos están en desuso.

Entonces, desde Java 8 considere usar Instant (inmutable, seguro para subprocesos, consciente de los segundos intercalares) escriba en lugar de Date. ÁRBITRO: Instante

  static final LocalTime MARKETS_OPEN = LocalTime.of(07, 00);
  static final LocalTime MARKETS_CLOSE = LocalTime.of(20, 00);

    // Instant utcTime = testDate.toInstant();
    var bigAppleTime = ZonedDateTime.ofInstant(utcTime, ZoneId.of("America/New_York"));

dentro de la gama INCLUYE:

    return !bigAppleTime.toLocalTime().isBefore(MARKETS_OPEN)
        && !bigAppleTime.toLocalTime().isAfter(MARKETS_CLOSE);

dentro de la gama EXCLUSIVA:

    return bigAppleTime.toLocalTime().isAfter(MARKETS_OPEN)
        && bigAppleTime.toLocalTime().isBefore(MARKETS_CLOSE);

avatar de usuario
keval dholakiya

si quieres una comparación inclusiva con LocalDate entonces usa este código.

LocalDate from = LocalDate.of(2021,8,1);
LocalDate to = LocalDate.of(2021,8,1);
LocalDate current = LocalDate.of(2021,8,1);

boolean isDateInRage = ( ! (current.isBefore(from.minusDays(1)) && current.isBefore(to.plusDays(1))) );

  • Un poco complicado, y quizás por eso tampoco del todo correcto. Cambié currentpara LocalDate.of(2021, 7, 31); y todavía tengo true, que no puede ser correcto. Utilizando LocalDate y isBefore() es una buena idea.

    – Olé VV

    8 de enero de 2021 a las 21:08


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad