¿Cómo obtener la hora de inicio y finalización de un día?
código como este no es exacto:
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
No tiene una precisión de milisegundos.
Respuestas:
tl; dr
Inicio del día
Obtenga la longitud completa de hoy como se ve en una zona horaria.
Utilizando el enfoque Half-Open, donde el principio es inclusivo mientras que el final es exclusivo . Este enfoque resuelve la falla en su código que no tiene en cuenta el último segundo del día.
Ver los mismos momentos en UTC.
Si desea el día completo de una fecha como se ve en UTC en lugar de en una zona horaria, use
OffsetDateTime
.Estos
OffsetDateTime
objetos ya estarán en UTC, pero puede llamartoInstant
si los necesita, que siempre están en UTC por definición.Sugerencia: Puede que le interese agregar la biblioteca ThreeTen-Extra a su proyecto para usar su
Interval
clase para representar este par deInstant
objetos. Esto ofrece la clase métodos útiles para la comparación comoabuts
,overlaps
,contains
, y mucho más.Medio abierto
La respuesta de mprivat es correcta. Su punto es no tratar de obtener el final del día, sino compararlo con "antes del comienzo del día siguiente". Su idea se conoce como el enfoque "Half-Open" donde un lapso de tiempo tiene un comienzo que es inclusivo mientras que el final es exclusivo .
Joda-Time 2.3 ofrece un método para este mismo propósito, para obtener un primer momento del día:
withTimeAtStartOfDay()
. Del mismo modo, en java.time,LocalDate::atStartOfDay
.Busque en StackOverflow "joda medio abierto" para ver más debates y ejemplos.
Vea esta publicación, Los intervalos de tiempo y otros rangos deben estar medio abiertos , por Bill Schneider.
Evite las clases de fecha y hora heredadas
Las clases java.util.Date y .Calendar son notoriamente problemáticas. Evítales.
Utilice clases de java.time . El marco java.time es el sucesor oficial de la exitosa biblioteca Joda-Time .
java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Adaptado a Java 6 y 7 en el proyecto ThreeTen-Backport , más adaptado a Android en el proyecto ThreeTenABP .
Un
Instant
es un momento en la línea de tiempo en UTC con una resolución de nanosegundos .Aplique una zona horaria para obtener la hora del reloj de pared de alguna localidad.
Para obtener el primer momento del día, repase la
LocalDate
clase y suatStartOfDay
método.Usando el enfoque Half-Open, obtenga el primer momento del día siguiente.
Actualmente, el marco java.time carece de una
Interval
clase como se describe a continuación para Joda-Time. Sin embargo, el proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es el campo de pruebas para posibles adiciones futuras a java.time. Entre sus clases se encuentraInterval
. Construye unInterval
pasando un par deInstant
objetos. Podemos extraer unInstant
de nuestrosZonedDateTime
objetos.Acerca de java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como
java.util.Date
,Calendar
, ySimpleDateFormat
.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 .
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
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 cuerdas, no se necesitan
java.sql.*
clases. Hibernate 5 y JPA 2.2 admiten java.time .¿Dónde obtener las clases java.time?
Joda-Time
ACTUALIZACIÓN: El proyecto Joda-Time ahora está en modo de mantenimiento y recomienda la migración a las clases java.time . Dejo esta sección intacta para la historia.
Joda-Time tiene tres clases para representar un espacio de tiempo de varias maneras:
Interval
,Period
, yDuration
. AnInterval
tiene un comienzo y un final específicos en la línea de tiempo del Universo. Esto se ajusta a nuestra necesidad de representar "un día".Llamamos al método en
withTimeAtStartOfDay
lugar de establecer la hora del día en ceros. Debido al horario de verano y otras anomalías, el primer momento del día puede no serlo00:00:00
.Código de ejemplo usando Joda-Time 2.3.
Si es necesario, puede convertirlo a java.util.Date.
fuente
LocalDateTime
Java 8
Actualización : he agregado estos 2 métodos a mis clases de utilidad de Java aquí
Está en el repositorio central de Maven en:
Java 7 y versiones anteriores
Con Apache Commons
Sin Apache Commons
fuente
getStartOfDay
debería ser:LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
es decir, LocalTime, no LocalDateTime.getEndOfDay(Date date)
.getStartOfDay(Date date)
Los métodos en la sección de Java 8 son correctos, a saber, LocalDateTime.MAX y .MIN lo ubican en las fechas más tempranas posibles en el pasado y en el futuro, no el comienzo y el final de un día. En su lugar, sugeriría .atStartOfDay () para el inicio y .plusDays (1) .atStartOfDay (). MinusNanos (1) para el final.localDateTimeToDate(LocalDateTime startOfDay)
arroja una excepción - java.lang.IllegalArgumentException: java.lang.ArithmeticException: overflow largoen getEndOfDay, puede agregar:
Aunque matemáticamente hablando, no puede especificar el final de un día más que diciendo que es "antes del comienzo del día siguiente".
Así que en lugar de decir
if(date >= getStartOfDay(today) && date <= getEndOfDay(today))
, debe decir:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))
. Esa es una definición mucho más sólida (y no tiene que preocuparse por la precisión de milisegundos).fuente
java.time
Usando el
java.time
marco integrado en Java 8.fuente
Local…
clases no tienen concepto de zonas horarias y se ajustan a anomalías. Por ejemplo, algunas zonas horarias tienen un cambio de horario de verano a la medianoche, por lo que el primer momento del día es a la hora01:00:00.0
(1 am) en lugar del00:00:00.0
valor producido por este código. Úselo en suZonedDateTime
lugar.Una forma adicional de encontrar el inicio del día con java8 java.time.ZonedDateTime en lugar de pasar
LocalDateTime
es simplemente truncar la entrada ZonedDateTime a DAYS:fuente
Para java 8, las siguientes declaraciones de una sola línea están funcionando. En este ejemplo utilizo la zona horaria UTC. Considere cambiar la zona horaria que utiliza actualmente.
Si no hay diferencia horaria con la salida. Tratar:
ZoneOffset.ofHours(0)
fuente
toInstant
es una sintaxis ilegal y conceptualmente redundante.Java 8 o ThreeTenABP
ZonedDateTime
LocalDateTime
Espero que ayude a alguien.
fuente
¡Probé este código y funciona bien!
fuente
ZonedDateTime
yaInstant
su disposición no es necesario que lo utilice nuncajava.sql.Timestamp
. Esa clase es una de las terribles clases antiguas heredadas ahora suplantadas por las clases java.time . A partir de JDBC 4.2, podemos intercambiar directamente objetos java.time con la base de datos. Su mezcla de clases tradicionales y modernas no tiene sentido para mí.Otra solución que no depende de ningún marco es:
Tenga en cuenta que devuelve la hora basada en UTC
fuente
calendar.setTimeInMillis (0); le da una precisión de hasta milisegundos
fuente
Sé que es un poco tarde, pero en el caso de Java 8, si está usando OffsetDateTime (que ofrece muchas ventajas, como TimeZone, Nanoseconds, etc.), puede usar el siguiente código:
fuente
Tuve varios inconvenientes con todas las soluciones porque necesitaba el tipo de variable Instant y la Zona horaria siempre interfería cambiando todo, luego combinando soluciones vi que esta es una buena opción.
y tenemos como resultado
Espero que te ayude
fuente
Instant
objetos. Sugerencia: puede que le interese agregar la biblioteca ThreeTen-Extra a su proyecto para usar suInterval
clase.Creo que lo más fácil sería algo como:
Estos milis se pueden convertir en Calendar, Instant o LocalDate según sus requisitos con Joda Time.
fuente
fuente