1. Introduction
En nuestro mundo, cada país sigue una cierta zona horaria. Estas zonas horarias son cruciales para expresar el tiempo de forma conveniente y efectiva. Sin embargo, las zonas horarias pueden resultar confusas debido a variables como el horario de verano. Además, al representar estas zonas horarias en nuestro código, puede surgir confusión. Java ha proporcionado múltiples clases como Date, Time y DateTime en el pasado para encargarse también de las zonas horarias. Sin embargo, las nuevas versiones de Java han introducido clases más útiles y expresivas como ZoneId y ZoneOffset para gestionar las zonas horarias.
En este artículo, discutiremos ZoneId y ZoneOffset, así como las clases DateTime relacionadas. También podemos leer sobre el nuevo conjunto de clases DateTime introducidas en Java 8, en nuestro post anterior.
2. ZoneId y ZoneOffset
Con la llegada de JSR-310, se añadieron algunas APIs útiles para gestionar fechas, horas y zonas horarias. Las clases ZoneId y ZoneOffset también fueron añadidas como parte de esta actualización.
2.1. ZoneId
Como se indicó anteriormente, ZoneId es una representación de la zona horaria como ‘Europe/Paris‘. Existen dos implementaciones de ZoneId. La primera, con un desplazamiento fijo en comparación con GMT/UTC. Y la segunda, como una región geográfica, que tiene un conjunto de reglas para calcular el desplazamiento respecto a GMT/UTC.
Veamos cómo se crea un ZoneId para Berlín, Alemania:
ZoneId zone = ZoneId.of("Europe/Berlin");
2.2. ZoneOffset
ZoneOffset extiende ZoneId y define el desplazamiento fijo de la zona horaria actual con GMT/UTC, como +02:00. Esto significa que este número representa horas y minutos fijos, representando la diferencia entre la hora en la zona horaria actual y GMT/UTC:
LocalDateTime now = LocalDateTime.now();
ZoneId zone = ZoneId.of("Europe/Berlin");
ZoneOffset zoneOffSet = zone.getRules().getOffset(now);
En caso de que un país tenga dos desplazamientos diferentes – en verano e invierno, habrá dos diferentes implementaciones de ZoneOffset para la misma región, de ahí la necesidad de especificar un LocalDateTime.
3. Clases DateTime
A continuación, discutamos algunas clases DateTime que realmente aprovechan ZoneId y ZoneOffset.
3.1. ZonedDateTime
ZonedDateTime es una representación inmutable de una fecha-hora con una zona horaria en el sistema calendario ISO-8601, como 2007-12-03T10:15:30+01:00 Europe/Paris. Un ZonedDateTime mantiene un estado equivalente a tres objetos separados: un LocalDateTime, un ZoneId y el ZoneOffset resuelto.
Esta clase almacena todos los campos de fecha y hora, hasta una precisión de nanosegundos, y una zona horaria, con un ZoneOffset, para manejar fechas-hora locales ambiguas. Por ejemplo, ZonedDateTime puede almacenar el valor “2 de octubre de 2007 a las 13:45:30.123456789 +02:00 en la zona horaria de Europa/París”.
Veamos cómo obtener el ZonedDateTime actual para la región anterior:
ZoneId zone = ZoneId.of("Europe/Berlin");
ZonedDateTime date = ZonedDateTime.now(zone);
ZonedDateTime también proporciona funciones incorporadas para convertir una fecha dada de una zona horaria a otra:
ZonedDateTime destDate = sourceDate.withZoneSameInstant(destZoneId);
3.2. OffsetDateTime
OffsetDateTime es una representación inmutable de una fecha-hora con un desplazamiento en el sistema calendario ISO-8601, como 2007-12-03T10:15:30+01:00. Esta clase almacena todos los campos de fecha y hora, hasta una precisión de nanosegundos, así como el desplazamiento desde GMT/UTC. Por ejemplo, OffsetDateTime puede almacenar el valor “2 de octubre de 2007 a las 13:45:30.123456789 +02:00”.
Veamos cómo obtener el OffsetDateTime actual con un desplazamiento de 2 horas respecto a GMT/UTC:
ZoneOffset zoneOffSet= ZoneOffset.of("+02:00");
OffsetDateTime date = OffsetDateTime.now(zoneOffSet);
3.3. OffsetTime
OffsetTime es un objeto de fecha-hora inmutable que representa una hora, a menudo vista como hora-minuto-segundo-desplazamiento, en el sistema calendario ISO-8601, como 10:15:30+01:00. Esta clase almacena todos los campos de hora, hasta una precisión de nanosegundos, así como un desplazamiento de zona. Por ejemplo, OffsetTime puede almacenar el valor “13:45:30.123456789+02:00”.
Veamos cómo obtener el OffsetTime actual con 2 horas de desplazamiento:
ZoneOffset zoneOffSet = ZoneOffset.of("+02:00");
OffsetTime time = OffsetTime.now(zoneOffSet);
4. Conclusion
Volviendo al punto central, ZoneOffset es una representación de la zona horaria en términos de la diferencia entre GMT/UTC y el tiempo dado. Esta es una forma práctica de representar las zonas horarias, aunque hay otras representaciones disponibles. Además, ZoneId y ZoneOffset no solo se utilizan de forma independiente, sino también por ciertas clases de Java como ZonedDateTime, OffsetDateTime y OffsetTime.
Consejos Prácticos para Programadores de Java
- Entender el Uso de Zonas Horarias: Asegúrate de comprender bien cómo y por qué usar ZoneId y ZoneOffset en tus proyectos. Esto te ayudará a evitar errores de cálculo de tiempo en aplicaciones distribuidas.
- Utiliza ZonedDateTime para Fechas Ambiguas: Siempre que manejes la fecha y hora de diferentes regiones geográficas, opta por ZonedDateTime para evitar ambigüedades.
- Mantén tu Código Limpio y Documentado: Como siempre, un buen comentario y documentación sobre tu implementación de fechas y horas ayudarán a otros a entender la lógica detrás de tu trabajo.
Aprovechar las nuevas API de fechas y horas introducidas en Java 8 puede facilitar mucho tu trabajo como desarrollador. Implementa correctamente estas clases en tus proyectos y verás mejoras en la claridad y eficacia de tu código.