Fecha de corte Java información de tiempo

Tengo un objeto Java Date que contiene información de fecha y hora. Quiero escribir un método que corte la información del tiempo, trunca las horas-minutos-segundos, por lo que solo me queda la fecha.

Ejemplo de entrada:

2008-01-01 13:15:00 

Rendimiento esperado:

 2008-01-01 00:00:00 

¿Tienes un consejo? Intenté hacer algo como esto:

 (timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000) 

pero tuve problemas con la zona horaria.

La forma recomendada de hacer una manipulación de fecha / hora es usar un objeto de Calendar :

 Calendar cal = Calendar.getInstance(); // locale-specific cal.setTime(dateObject); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); long time = cal.getTimeInMillis(); 

¿Has mirado el método truncado DateUtils en Apache Commons Lang?

 Date truncatedDate = DateUtils.truncate(new Date(), Calendar.DATE); 

eliminará el elemento de tiempo.

¿Has mirado a Joda ? Es una forma mucho más fácil e intuitiva de trabajar con fechas y horas. Por ejemplo, puede convertir trivialmente entre (digamos) objetos LocalDateTime y LocalDate .

ej. (para ilustrar la API)

 LocalDate date = new LocalDateTime(milliseconds).toLocalDate() 

Además, resuelve algunos problemas de seguridad de subprocesos con los formateadores de fecha / hora y se recomienda encarecidamente para trabajar con problemas de fecha / hora en Java.

 Date date = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); date = cal.getTime(); 

Con Joda puedes obtener fácilmente la fecha esperada.

A partir de la versión 2.7 (tal vez desde una versión anterior superior a 2.2), como comenta un comentarista, toDateMidnight ha quedado en desuso a favor o en el nombre apropiado withTimeAtStartOfDay() , por lo que es conveniente

 DateTime.now().withTimeAtStartOfDay() 

posible.

Beneficio agregado de una API mucho más agradable.

Con versiones anteriores, puedes hacer

 new DateTime(new Date()).toDateMidnight().toDate() 

Solo una actualización rápida a la luz de las clases java.time ahora integradas en Java 8 y posterior.

LocalDateTime tiene un método truncatedTo que aborda con eficacia de lo que está hablando aquí:

 LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES) 

Esto expressá el tiempo actual en minutos solamente:

 2015-03-05T11:47 

Puede usar cualquier ChronoUnit (o cualquier TemporalUnit ) para ejecutar el truncamiento.

Para marcas de tiempo:

 timestamp -= timestamp % (24 * 60 * 60 * 1000) 

Use DateUtils de Apache, con truncado, como este:

 DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE); 

Hice el truncamiento con la nueva API java8. Me enfrenté a algo extraño, pero en general es trunco ​​…

 Instant instant = date.toInstant(); instant = instant.truncatedTo(ChronoUnit.DAYS); date = Date.from(instant); 

De java.util.Date JavaDocs:

La clase Date representa un instante específico en el tiempo, con precisión de milisegundos

y de los JavaDocs java.sql.Date:

Para cumplir con la definición de SQL DATE, los valores de milisegundos envueltos por una instancia de java.sql.Date deben ‘normalizarse’ al establecer las horas, minutos, segundos y milisegundos en cero en la zona horaria particular a la que está asociada la instancia. .

Entonces, el mejor enfoque es usar java.sql.Date si no necesita la parte de tiempo

 java.util.Date utilDate = new java.util.Date(); java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis()); 

y el resultado es:

 java.util.Date : Thu Apr 26 16:22:53 PST 2012 java.sql.Date : 2012-04-26 

Utilice el método set() la clase Calendar para establecer los HOUR_OF_DAY, MINUTE, SECOND y MILLISECOND en cero.

La pregunta es contradictoria. Pide una fecha sin una hora del día pero muestra un ejemplo con un tiempo de 00:00:00 .

Joda-Time

ACTUALIZACIÓN: El proyecto Joda-Time ahora está en modo de mantenimiento , y el equipo recomienda la migración a las clases java.time . Vea mi otra respuesta para la solución java.time.

Si, por el contrario, desea establecer la hora del día en el primer momento del día, utilice un objeto DateTime en la biblioteca Joda-Time y llame a su método withTimeAtStartOfDay . Tenga en cuenta que el primer momento puede no ser el horario 00:00:00 debido al horario de verano o tal vez a otras anomalías.

Simplemente clear() los campos redundantes.

 Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.clear(Calendar.MINUTE); calendar.clear(Calendar.SECOND); calendar.clear(Calendar.MILLISECOND); Date truncatedDate = calendar.getTime(); 

Realmente me molesta que el nuevo constructor de calendario “mejorado” no tome un int por milisegundos como el “horrible” Fecha uno. Entonces realmente me crucé y escribí esto:

 long stuffYou = startTime.getTimeInMillis() % 1000; startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou); 

No usé la palabra “cosas” en ese momento, pero luego descubrí la felicidad de esto:

 startTime.set(Calendar.MILLISECOND, 0); 

Pero todavía estoy bastante en contra de eso.

Puedes hacer esto para evitar el problema de la zona horaria:

 public static Date truncDate(Date date) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } 

Aunque el objeto Java Date es el valor de la marca de tiempo, pero durante el truncado, se convertirá a la zona horaria local, por lo que obtendrá un valor sorprendente si espera un valor de la zona horaria UTC.

tl; dr

 LocalDateTime.parse( // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time. "2008-01-01 13:15:00".replace( " " , "T" ) // Alter input string to comply with ISO 8601 standard format. ) .toLocalDate() // Extract a date-only value. .atStartOfDay( // Do not assume the day starts at 00:00:00. Let class determine start-of-day. ZoneId.of( "Europe/Paris" ) // Determining a specific start-of-day requires a time zone. ) // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline. .toString() // Generate a String in standard ISO 8601 format, wisely extended to append the name of the time zone in square brackets. 

2008-01-01T00: 00 + 01: 00 [Europa / París]

Para generar una cadena en el formato deseado, pase un DateTimeFormatter .

 LocalDateTime.parse( // Lacking an offset or time zone, parse as a `LocalDateTime`. *Not* a specific moment in time. "2008-01-01 13:15:00".replace( " " , "T" ) // Alter input string to comply with ISO 8601 standard format. ) .toLocalDate() // Extract a date-only value. .atStartOfDay( // Do not assume the day starts at 00:00:00. Let class determine start-of-day. ZoneId.of( "Europe/Paris" ) // Determining a specific start-of-day requires a time zone. ) // Result is a `ZonedDateTime` object. At this point we have a specific moment in time, a point on the timeline. .format( // Generate a String representing the object's value. DateTimeFormatter.ISO_LOCAL_DATE_TIME // Built-in predefined formatter close to what you want. ) .replace( "T" , " " ) // Replace the standard's use of a 'T' in the middle with your desired SPACE character. 

2008-01-01 00:00:00

Detalles

Otras respuestas son correctas, pero usan antiguas clases de fecha y hora ahora pasadas de moda por el framework java.time.

java.time

El marco java.time está integrado en Java 8 y posterior. Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 ( ThreeTen-Backport ) y se adapta aún más a Android ( ThreeTenABP ).

Primero modifique la cadena de entrada para cumplir con la versión canónica del formato ISO 8601. Los formatos estándar ISO 8601 se utilizan por defecto en las clases java.time para analizar / generar cadenas que representan valores de fecha y hora. Necesitamos reemplazar ese ESPACIO en el medio con una T

 String input = "2008-01-01 13:15:00".replace( " " , "T" ); // → 2008-01-01T13:15:00 

Ahora podemos analizarlo como LocalDateTime , donde “Local” significa ninguna localidad específica. La entrada carece de cualquier compensación de UTC o información de zona horaria.

 LocalDateTime ldt = LocalDateTime.parse( input ); 

ldt.toString () … 2008-01-01T13: 15: 00

Si no le importa la hora del día ni la zona horaria, LocalDate en LocalDate .

 LocalDate ld = ldt.toLocalDate(); 

ld.toString () … 2008-01-01

Primer momento del día

Si, en cambio, desea que la hora del día se establezca en el primer momento del día, utilice una clase ZonedDateTime , luego LocalDate un objeto LocalDate para llamar a su método atStartOfDay . Tenga en cuenta que el primer momento puede no ser el horario 00:00:00 debido al horario de verano o tal vez a otras anomalías.

La zona horaria es crucial porque, en cualquier momento, la fecha varía según el mundo por zona. Por ejemplo, unos minutos después de la medianoche en París es un nuevo día para los parisinos, pero todavía es “ayer” en Montreal para los canadienses.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ldt.atZone( zoneId ); LocalDate ldFromZdt = zdt.toLocalDate(); ZonedDateTime zdtStartOfDay = ldFromZdt.atStartOfDay( zoneId ); 

zdtStartOfDay.toString () … 2008-01-01T00: 00: 00-05: 00 [America / Montreal]

UTC

Para ver ese momento a través de la lente de la zona horaria UTC , extrae un objeto Instant . Tanto ZonedDateTime como Instant representarán el mismo momento en la línea de tiempo pero aparecerán como dos tiempos diferentes de reloj de pared .

Un Instant es la clase básica de building-block en java.time, siempre en UTC por definición. Utilice esta clase con frecuencia, ya que generalmente debe hacer su lógica comercial, almacenamiento de datos e intercambio de datos en UTC.

 Instant instant = zdtStartOfDay.toInstant(); 

instant.toString () … 2008-01-01T05: 00: 00Z

Vemos las 5 AM en lugar del trazo de la medianoche. En formato estándar, la Z en el extremo es corta para Zulu y significa “UTC”.


Acerca de java.time

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

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

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 .

Puede intercambiar objetos java.time directamente con su base de datos. Use un controlador JDBC que cumpla con JDBC 4.2 o posterior. Sin necesidad de cadenas, sin necesidad de clases java.sql.* .

¿Dónde obtener las clases de java.time?

  • Java SE 8 , Java SE 9 y posterior
    • Incorporado.
    • Parte de la API Java estándar con una implementación integrada.
    • Java 9 agrega algunas características y correcciones menores.
  • Java SE 6 y Java SE 7
    • Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 en ThreeTen-Backport .
  • Androide
    • Versiones posteriores de las implementaciones del paquete de Android de las clases java.time.
    • Para Android anterior (<26), el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Consulte Cómo utilizar ThreeTenABP ….

El proyecto ThreeTen-Extra amplía java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval , YearWeek , YearQuarter y más .

Puede ser una respuesta tardía, pero aquí hay una manera de hacerlo en una línea sin usar ninguna biblioteca:

 new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP)) 

Para todas las respuestas que usan Calendar, deberías usarlo así en su lugar

 public static Date truncateDate(Date date) { Calendar c = Calendar.getInstance(); c.setTime(date); c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY)); c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE)); c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND)); c.set(Calendar.MILLISECOND, c.getActualMinimum(Calendar.MILLISECOND)); return c.getTime(); } 

Pero prefiero esto:

 public static Date truncateDate(Date date) { return new java.sql.Date(date.getTime()); } 

Solucioné el problema de esta manera (en la zona ocho oriental (hora de Beijing)):

 private Date getTruncatedDate(Date d) { if (d == null) { return null; } long h = 60 * 60 * 1000L; long dateStamp = d.getTime() - (d.getTime() + 8 * h) % (24 * h); return new Date(dateStamp); } 

Antes que nada, debes tener claro qué es la marca de tiempo. La marca de tiempo es el milisegundo total desde el 1 de enero de 00:00:00 de 1970 de GMT (igual que el UTC) o el jueves de 01 de agosto a las 08:00:00 CST de 1970 hasta ahora.

Recuerde: la marca de tiempo es independiente de la zona horaria.

Entonces obtienes el mismo resultado con la siguiente statement en diferentes husos horarios:

 System.out.println(new Date().getTime()); 

Y

 System.out.println(new Date(0)); 

imprime información de tiempo diferente en diferentes zonas horarias: si configura la zona horaria de su PC como UTC, obtiene

 Thu Jan 01 00:00:00 UTC 1970 

Pero si configura la zona horaria como (UTC +8: 00) Beijing, Chongqing, Hong Kong, Urumq, obtiene:

 Thu Jan 01 08:00:00 CST 1970 

Java recibe la marca de tiempo y luego muestra la información de fecha y hora de acuerdo con la zona horaria.

Para la introducción de cómo Java muestra información de fecha y hora en diferentes zonas horarias, la forma de trancanear la información de tiempo es fácil. Debería obtener la marca de tiempo y tener en cuenta la zona horaria cuando se corta la información de tiempo. A continuación, puede crear un nuevo objeto Fecha con la marca de tiempo de corte (podemos llamarlo sello de fecha), java compensará la zona horaria cuando se muestre la información de fecha.

Al igual que en la zona ocho oriental (hora de Beijing), la hora de Beijing es anterior 8 horas que GMT, por lo que debe restar más 8 horas cuando se realiza la operación de módulo. Es decir, debe obtener la hora GMT primero, luego Java agregará 8 horas cuando se muestre según la configuración de zona horaria de su PC.


El problema de la zona horaria es oscuro, y también me desconcierta por un largo tiempo. Ahora lo dejo en claro. Hope ayuda.


2018-01-04 El siguiente método también funciona.

 private Date getTruncatedDate2(Date d) { Calendar cal = Calendar.getInstance(); // locale-specific cal.setTime(d); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); 

}

Con Joda-Time desde la versión 2.0, puede usar LocalDate.toDate() .

Simplemente

 // someDatetime is whatever java.util.Date you have. Date someDay = new LocalDate(someDatetime).toDate();