1. Información general
Antes de Java 8, java.util.Date era una de las clases más utilizadas para representar valores de fecha y hora en Java.
Luego, Java 8 introdujo java.time.LocalDateTime y java.time.ZonedDateTime. Java 8 también nos permite representar un tiempo específico en la línea de tiempo usando java.time.Instant.
En este tutorial, aprenderemos a sumar o restar n horas de una fecha y hora determinada en Java . Primero veremos algunas clases estándar de Java relacionadas con la fecha y la hora, y luego mostraremos algunas opciones de terceros.
Para obtener más información sobre Java 8 DateTime API, le sugerimos que lea este artículo.
2. java.util.Date
Si usamos Java 7 o versiones anteriores, podemos usar las clases java.util.Date y java.util.Calendar para la mayor parte del manejo relacionado con la fecha y la hora.
Veamos cómo agregar n horas a un objeto Date dado :
public Date addHoursToJavaUtilDate(Date date, int hours) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.HOUR_OF_DAY, hours); return calendar.getTime(); }
Tenga en cuenta que Calendar.HOUR_OF_DAY se refiere a un reloj de 24 horas .
El método anterior devuelve un nuevo objeto Date , cuyo valor sería (fecha + horas) o (fecha - horas) , dependiendo de si pasamos un valor positivo o negativo de horas respectivamente.
Supongamos que tenemos una aplicación Java 8, pero queremos seguir trabajando con las instancias java.util.Date .
Para tal caso, podemos optar por adoptar el siguiente enfoque alternativo:
- Utilice el método java.util.Date toInstant () para convertir un objeto Date en una instancia java.time.Instant
- Agregue una duración específica al objeto java.time.Instant usando el método plus ()
- Recupere nuestra instancia java.util.Date pasando el objeto java.time.Instant al método java.util.Date.from ()
Echemos un vistazo rápido a este enfoque:
@Test public void givenJavaUtilDate_whenUsingToInstant_thenAddHours() { Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0) .getTime(); Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0) .getTime(); assertThat(Date.from(actualDate.toInstant().plus(Duration.ofHours(2)))) .isEqualTo(expectedDate); }
Sin embargo, tenga en cuenta que siempre se recomienda utilizar la nueva API DateTime para todas las aplicaciones en Java 8 o versiones superiores.
3. java.time.LocalDateTime / ZonedDateTime
En Java 8 o posterior, agregar horas a una instancia java.time.LocalDateTime o java.time.ZonedDateTime es bastante sencillo y hace uso del método plusHours () :
@Test public void givenLocalDateTime_whenUsingPlusHours_thenAddHours() { LocalDateTime actualDateTime = LocalDateTime .of(2018, Month.JUNE, 25, 5, 0); LocalDateTime expectedDateTime = LocalDateTime. of(2018, Month.JUNE, 25, 10, 0); assertThat(actualDateTime.plusHours(5)).isEqualTo(expectedDateTime); }
¿Y si deseamos restar algunas horas?
Pasar un valor negativo de horas al método plusHours () estaría bien. Sin embargo, se recomienda utilizar el método minusHours () :
@Test public void givenLocalDateTime_whenUsingMinusHours_thenSubtractHours() { LocalDateTime actualDateTime = LocalDateTime .of(2018, Month.JUNE, 25, 5, 0); LocalDateTime expectedDateTime = LocalDateTime .of(2018, Month.JUNE, 25, 3, 0); assertThat(actualDateTime.minusHours(2)).isEqualTo(expectedDateTime); }
Los métodos plusHours () y minusHours () en java.time.ZonedDateTime funcionan exactamente de la misma manera.
4. java.time.Instant
Como sabemos, java.time.Instant introducido en Java 8 DateTime API representa un momento específico en la línea de tiempo.
Para agregar algunas horas a un objeto Instant , podemos usar su método plus () con un java.time.temporal.TemporalAmount :
@Test public void givenInstant_whenUsingAddHoursToInstant_thenAddHours() { Instant actualValue = Instant.parse("2018-06-25T05:12:35Z"); Instant expectedValue = Instant.parse("2018-06-25T07:12:35Z"); assertThat(actualValue.plus(2, ChronoUnit.HOURS)) .isEqualTo(expectedValue); }
De manera similar, el método minus () se puede usar para restar un TemporalAmount específico .
5. Apache Commons DateUtils
La clase DateUtils de la biblioteca Apache Commons Lang expone un método addHours () estático :
public static Date addHours(Date date, int amount)
El método toma un objeto java.util.Date junto con una cantidad que deseamos agregarle, cuyo valor podría ser positivo o negativo.
Se devuelve un nuevo objeto java.util.Date como resultado:
@Test public void givenJavaUtilDate_whenUsingApacheCommons_thenAddHours() { Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0) .getTime(); Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0) .getTime(); assertThat(DateUtils.addHours(actualDate, 2)).isEqualTo(expectedDate); }
La última versión de Apache Commons Lang está disponible en Maven Central.
6. Hora de Joda
Joda Time es una alternativa a la API DateTime de Java 8 y proporciona sus propias implementaciones DateTime .
La mayoría de sus clases relacionadas con DateTime exponen los métodos plusHours () y minusHours () para ayudarnos a sumar o restar un número determinado de horas de un objeto DateTime .
Veamos un ejemplo:
@Test public void givenJodaDateTime_whenUsingPlusHoursToDateTime_thenAddHours() { DateTime actualDateTime = new DateTime(2018, 5, 25, 5, 0); DateTime expectedDateTime = new DateTime(2018, 5, 25, 7, 0); assertThat(actualDateTime.plusHours(2)).isEqualTo(expectedDateTime); }
Podemos comprobar fácilmente la última versión disponible de Joda Time en Maven Central.
7. Conclusión
En este tutorial, cubrimos varias formas de sumar o restar una cantidad determinada de horas de los valores estándar de fecha y hora de Java.
También analizamos algunas bibliotecas de terceros como alternativa. Como de costumbre, el código fuente completo está disponible en GitHub.