¿Cómo verifico si una fecha está dentro de un rango determinado?
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.
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.
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.time
marco integrado. Reemplaza las antiguas y problemáticas clases incluidas java.util.Date/.Calendar
y SimpleDateFormat
. Inspirado en la exitosa biblioteca Joda-Time. Definido por JSR 310. Ampliado por el proyecto ThreeTen-Extra.
An Instant
es un momento en la línea de tiempo en UTC con una resolución de nanosegundos.
Instant
Convierte tus java.util.Date
objetos en objetos instantáneos.
Instant start = myJUDateStart.toInstant();
Instant stop = …
Si obtiene java.sql.Timestamp
objetos a través de JDBC desde una base de datos, conviértalos a java.time.Instant de manera similar. A java.sql.Timestamp
ya 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 LocalDate
clase 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
, isBefore
y isAfter
para 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 Interval
clase 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 Interval
clase trabaja con Instant
objetos. La Instant
clase 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 LocalDate
a 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
, Calendar
y SimpleDateFormat
.
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las java.time
clases.
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.time
clases?
- 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.time
funcionalidad 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 .YearWeek
YearQuarter
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.
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.