¿Cómo crear un objeto Java Date de la medianoche de hoy y de la medianoche de mañana?

En mi código necesito encontrar todas mis cosas que sucedieron hoy. Entonces, debo comparar las fechas desde hoy a las 00:00 a.m. (medianoche temprano esta mañana) a las 12:00 p.m. (medianoche esta noche).

Lo sé …

Date today = new Date(); 

… me entiende en este momento. Y …

 Date beginning = new Date(0); 

… me da tiempo cero el 1 de enero de 1970. Pero, ¿cuál es una forma fácil de obtener un tiempo cero hoy y un tiempo cero mañana?

ACTUALIZAR; Hice esto, pero seguramente hay una manera más fácil?

 Calendar calStart = new GregorianCalendar(); calStart.setTime(new Date()); calStart.set(Calendar.HOUR_OF_DAY, 0); calStart.set(Calendar.MINUTE, 0); calStart.set(Calendar.SECOND, 0); calStart.set(Calendar.MILLISECOND, 0); Date midnightYesterday = calStart.getTime(); Calendar calEnd = new GregorianCalendar(); calEnd.setTime(new Date()); calEnd.set(Calendar.DAY_OF_YEAR, calEnd.get(Calendar.DAY_OF_YEAR)+1); calEnd.set(Calendar.HOUR_OF_DAY, 0); calEnd.set(Calendar.MINUTE, 0); calEnd.set(Calendar.SECOND, 0); calEnd.set(Calendar.MILLISECOND, 0); Date midnightTonight = calEnd.getTime(); 

java.util.Calendar

 // today Calendar date = new GregorianCalendar(); // reset hour, minutes, seconds and millis date.set(Calendar.HOUR_OF_DAY, 0); date.set(Calendar.MINUTE, 0); date.set(Calendar.SECOND, 0); date.set(Calendar.MILLISECOND, 0); // next day date.add(Calendar.DAY_OF_MONTH, 1); 

JDK 8 – java.time.LocalTime y java.time.LocalDate

 LocalTime midnight = LocalTime.MIDNIGHT; LocalDate today = LocalDate.now(ZoneId.of("Europe/Berlin")); LocalDateTime todayMidnight = LocalDateTime.of(today, midnight); LocalDateTime tomorrowMidnight = todayMidnight.plusDays(1); 

Joda-Time

Si está utilizando un JDK <8, le recomiendo Joda Time , porque la API es realmente agradable:

 DateTime date = new DateTime().toDateMidnight().toDateTime(); DateTime tomorrow = date.plusDays(1); 

Como la versión 2.3 de Joda Time DateMidnight está en desuso , utilice esto:

 DateTime today = new DateTime().withTimeAtStartOfDay(); DateTime tomorrow = today.plusDays(1).withTimeAtStartOfDay(); 

Pase una zona horaria si no desea la zona horaria predeterminada actual de la JVM.

 DateTimeZone timeZone = DateTimeZone.forID("America/Montreal"); DateTime today = new DateTime(timeZone).withTimeAtStartOfDay(); // Pass time zone to constructor. 

Recuerde, la Date no se usa para representar fechas (!). Para representar la fecha necesitas un calendario. Esta:

 Calendar c = new GregorianCalendar(); 

creará una instancia de Calendar represente la fecha actual en su zona horaria actual. Ahora lo que necesita es truncar cada campo por debajo del día (hora, minuto, segundo y milisegundo) configurándolo en 0 . Ahora tienes una medianoche hoy.

Ahora, para llegar a la medianoche del día siguiente, debe agregar un día:

 c.add(Calendar.DAY_OF_MONTH, 1); 

Tenga en cuenta que agregar 86400 segundos o 24 horas es incorrecto debido al horario de verano que podría ocurrir mientras tanto.

ACTUALIZACIÓN: Sin embargo, mi forma favorita de lidiar con este problema es usar la clase DateUtils de Commons Lang :

 Date start = DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH)) Date end = DateUtils.addDays(start, 1); 

Utiliza el Calendar detrás de escena …

La forma más fácil de encontrar una medianoche:

 Long time = new Date().getTime(); Date date = new Date(time - time % (24 * 60 * 60 * 1000)); 

Día siguiente:

 Date date = new Date(date.getTime() + 24 * 60 * 60 * 1000); 

Para completar, si está utilizando Java 8 también puede usar el método truncatedTo de la clase Instant para obtener la medianoche en UTC .

 Instant.now().truncatedTo(ChronoUnit.DAYS); 

Como está escrito en el Javadoc

Por ejemplo, truncar con la unidad MINUTES redondeará al minuto más cercano, poniendo los segundos y nanosegundos a cero.

Espero eso ayude.

A partir de JodaTime 2.3, toDateMidnight() está en desuso.

Desde la actualización de 2.2 a 2.3

     Deprecations desde 2.2
     ----------------------
     - DateMidnight [# 41]
      Esta clase tiene fallas en el concepto
      La hora de la medianoche de vez en cuando no ocurre en algunas zonas horarias
      Esto es resultado de un horario de verano de 00:00 a 01:00
      DateMidnight es esencialmente un DateTime con un horario bloqueado a la medianoche
      Tal concepto es, en general, deficiente para usar, dado LocalDate
      Reemplazar fechaMidnight con LocalDate
      O reemplácelo con DateTime, quizás utilizando el método withTimeAtStartOfDay ()

Aquí hay un código de muestra sin el método toDateMidnight() .

Código

 DateTime todayAtMidnight = new DateTime().withTimeAtStartOfDay(); System.out.println(todayAtMidnight.toString("yyyy-MM-dd HH:mm:ss")); 

Salida ( puede ser diferente dependiendo de la zona horaria local )

 2013-09-28 00:00:00 

estos métodos te ayudarán-

 public static Date getStartOfDay(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } 

y

 public static Date getEndOfDay(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 59); calendar.set(Calendar.SECOND, 59); calendar.set(Calendar.MILLISECOND, 999); return calendar.getTime(); } 

java.time

Si está utilizando Java 8 y posterior, puede probar el paquete java.time ( Tutorial ):

 LocalDate tomorrow = LocalDate.now().plusDays(1); Date endDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant()); 

Esto parece ser una opción:

 DateFormat justDay = new SimpleDateFormat("yyyyMMdd"); Date thisMorningMidnight = justDay.parse(justDay.format(new Date())); 

para agregarle un día, ya sea

 Date tomorrow = new Date(thisMorningMidnight.getTime() + 24 * 60 * 60 * 1000); 

o

 Calendar c = Calendar.getInstance(); c.setTime(thisMorningMidnight); c.add(Calendar.DATE, 1); Date tomorrowFromCalendar = c.getTime(); 

Tengo la corazonada de que lo último es preferible en caso de algo extraño, como el ahorro de luz diurna, que hace que agregar 24 horas no sea suficiente (consulte https://stackoverflow.com/a/4336131/32453 y sus otras respuestas).

Otras respuestas son correctas, especialmente la respuesta java.time de arganzheng . Como mencionan algunos, debe evitar las antiguas clases de java.util.Date/.Calendar ya que están mal diseñadas, confusas y molestas. Han sido suplantados por las clases java.time.

Permítanme agregar notas sobre la estrategia en torno al manejo de la medianoche y los períodos de tiempo .

Medio abierto

En el trabajo de fecha y hora, los periodos de tiempo a menudo se definen utilizando el enfoque de “medio abierto”. En este enfoque, el comienzo es inclusivo, mientras que el final es exclusivo . Esto resuelve los problemas y si se usa de forma coherente, hace que el razonamiento sobre el manejo de la fecha y hora sea mucho más fácil.

Un problema resuelto es definir el final del día. ¿Es el último momento del día 23:59:59.999 ( milisegundos )? Tal vez, en la clase java.util.Date (desde la versión más antigua de Java, problemático, ¡evite esta clase!) Y en la exitosa librería Joda-Time . Pero en otro software, como una base de datos como Postgres, el último momento será 23:59:59.999999 ( microsegundos ). Pero en otro software como el marco java.time (integrado en Java 8 y posterior, sucesor de Joda-Time) y en alguna base de datos como H2 , el último momento podría ser 23:59.59.999999999 ( nanosegundos ). En lugar de dividir los pelos, piense en términos de primer momento solamente, no en el último momento.

En Half-Open, un día se extiende desde el primer momento de un día y continúa hasta el primer momento del día siguiente. Entonces, en lugar de pensar así:

… desde hoy a las 00:00 a.m. (medianoche temprano esta mañana) a las 12:00 p.m. (medianoche esta noche).

… piensa así …

desde el primer momento de hoy hasta el primer momento del mañana pero sin incluirlo:
(> = 00:00:00.0 hoy Y < 00:00:00.0 mañana)

En el trabajo de la base de datos, este enfoque significa no utilizar el operador BETWEEN en SQL.

Comienzo del día

Además, el primer momento del día no es siempre la hora del día 00:00:00.0 . El horario de verano (DST) en algunas zonas horarias, y posiblemente otras anomalías, puede significar que un horario diferente comience el día.

Deje que las clases java.time hagan el trabajo de determinar el comienzo de un día con una llamada a LocalDate::atStartOfDay( ZoneId ) . Por lo tanto, debemos LocalDate a LocalDate y volver a ZonedDateTime como puede ver en este código de ejemplo.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime now = ZonedDateTime.now( zoneId ); ZonedDateTime todayStart = now.toLocalDate().atStartOfDay( zoneId ); ZonedDateTime tomorrowStart = todayStart.plusDays( 1 ); 

Tenga en cuenta el paso del ZoneId opcional. Si se omite, la zona horaria predeterminada actual de su JVM se aplica implícitamente. Mejor ser explícito.

La zona horaria es crucial para el trabajo de fecha y hora. La pregunta y algunas otras respuestas son potencialmente defectuosas porque no manejan conscientemente la zona horaria.

Convertir

Si debe usar un java.util.Date o .Calendar, busque nuevos métodos de conversión agregados a esas clases antiguas.

 java.util.Date utilDate = java.util.Date.from( todayStart.toInstant() ); java.util.GregorianCalendar gregCal = java.util.GregorianCalendar.from( todayStart ); 

Lapso de tiempo

Por cierto, si está haciendo mucho trabajo con una gran cantidad de tiempo, eche un vistazo a:

  • Duration
  • Period
  • Interval
    La clase Interval se encuentra en el proyecto ThreeTen-Extra , una extensión del marco java.time. Este proyecto es el terreno de prueba para posibles adiciones futuras a java.time.
    Interval todayMontreal = Interval.of( todayStart.toInstant() , tomorrowStart.toInstant() );

Hice esto de manera diferente a todos los demás aquí. Soy nuevo en Java, así que tal vez mi solución es pobre.

 Date now = new Date(); Date midnightToday = new Date(now.getYear(), now.getMonth(), now.getDate()); 

No estoy seguro de que esto funcione todavía, pero de cualquier forma, agradecería cualquier comentario sobre esta solución.

Estoy confundido por la statement anterior que puede calcular mañana llamando:

 c.add(Calendar.DAY_OF_MONTH, 1); 

Si agrega 1 al día del mes y es el día 31, ¿no recibe el día 32 del mes?

¿Por qué las horas / fechas no están todas basadas en UTC en Java? Creo que las zonas horarias solo deberían ser necesarias cuando se usan con i / o, pero internamente siempre deberían usarse en UTC. Sin embargo, las clases parecen incluir información de zona horaria que parece no solo un desperdicio, sino que también es propenso a errores de encoding.

Casi como las respuestas anteriores, pero nadie mencionó el parámetro AM_PM:

  Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.AM_PM, Calendar.AM); 

La forma más simple con JodaTime

DateMidnight date = DateMidnight.now();

Debido a que un día es 24 * 60 * 60 * 1000 ms, la medianoche de este día se puede calcular como …

 long now = System.currentTimeMillis(); long delta = now % 24 * 60 * 60 * 1000; long midnight = now - delta; Date midnightDate = new Date(midnight);` 
 Date now= new Date(); // Today midnight Date todayMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY); // tomorrow midnight Date tomorrowMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY + DateUtils.MILLIS_PER_DAY); 

De forma anticuada..

 private static Date getDateWithMidnight(){ long dateInMillis = new Date().getTime(); return new Date(dateInMillis - dateInMillis%(1000*60*60*24) - TimeZone.getDefault().getOffset(dateInMillis)); } 

Sé que esta es una publicación muy antigua. ¡Pensé compartir mi conocimiento aquí!

Para la fecha Media noche de hoy con la zona horaria exacta, puede usar la siguiente

 public static Date getCurrentDateWithMidnightTS(){ return new Date(System.currentTimeMillis() - (System.currentTimeMillis()%(1000*60*60*24)) - (1000*60 * 330)); } 

Donde (1000*60 * 330) se resta, es decir, está realmente relacionado con la zona horaria, por ejemplo, la zona horaria de la India, es decir, kolkata difiere +5: 30 horas de la real. Así que restar eso con la conversión en milisegundos.

Así que cambie el último número sustraído según usted. Estoy creando un producto, es decir, solo con sede en India, así que solo usé una marca de tiempo específica.

 Date todayMidnightUTC = java.sql.Date.valueOf(LocalDate.now()); Date tomorrowMidnightUTC = java.sql.Date.valueOf(LocalDate.now().plusDays(1)); Date anyMidnightLocal = java.sql.Date.valueOf(LocalDate.from(dateTime.toInstant().atZone(ZoneId.systemDefault()))); 

Pero ten en cuenta que java.sql.Date.toInstant() siempre arroja UnsupportedOperationException .

¿A través de LocalDate a java.util.Date y viceversa una conversión más simple?