13 marzo, 2012

Actualización de la zona horaria en Java

Hasta que pasó... llegó el día del cambio de hora, pero se decidió aplazarlo hasta el 28 de abril.

Esto pasa con bastante frecuencia y en varios países. Se adelanta o se cambia el horario de verano y nuestros computadores son los primeros en sufrir las consecuencias.

Pero ¿que es lo que pasa?

En los sistemas operativos modernos, el reloj hardware del computador almacena la hora oficial universal (GMT/UTC) que en español significa que el reloj de nuestro computador está a la hora con el reloj de Greenwich, Inglaterra.

El Sistema Operativo deduce entonces la hora de una zona en base a la configuración de zona horaria y la hora UTC. Adicionalmente se utiliza la configuración de horario de verano (DST en ingles) para ajustar la hora a los estándares del momento.

Por ejemplo, aca en Chile continental, tradicionalmente el horario de verano comienza el segundo sábado de septiembre y termina el segundo sábado de marzo. Nuestra zona horaria es GMT -4, lo que significa que al horario de Greenwich se le restan 4 horas para obtener la hora de Chile continental.

Es decir: Hora de Chile continental  = Hora GMT/UTC - 4.

Hasta ahí, todo simple, pero además tenemos nuestras reglas de configuracion de horario de verano (DST). Estas reglas introducen un "delta" adicional a la zona horaria.

O sea: Hora de Chile continental  = Hora GMT/UTC - 4 +- DST.

El problema ocurre justamente con ese delta DST. Por regla general los sistemas operativos tratan de mantenerse actualizados y suelen hacerlo bastante bien, por lo que a menos que usemos un sistema sin soporte o con soporte escaso, esto no debiera presentar mayor inconveniente.

Java utiliza su propia información de zona horaria. Esto significa que aunque este configurado para uilizar la misma zona horaria del sistema operativo, la información DST que contiene no es la misma del sistema. Como resultado, aunque se actualice la información DST del sistema operativo, la maquina de Java no se verá afectada.

Y eso fue lo que pasó el sabado pasado. Mi computador se actualizó correctamente y se mantuvo a la hora oficial correcta, pero mis aplicaciones Java muestran la hora con una hora de atraso con respecto al computador:

Hora UTC: 16:00
Hora Chile Continental: 13:00
Hora PC: 13:00
Hora Java: 12:00

La máquina virtual Java "cree" que estamos en horario de invierno y por lo tanto muestra la hora que su información de zona horaria le indica que debe mostrar.

Se puede corregir de varias formas:

  • Mover la zona horaria del computador o cambiar la hora manualmente.
  • Actualizar la versión de Java.
  • Corregir la información de zona horaria de Java.
La opción 1 no es válida, a menos que solo usemos el computador para la aplicación Java conflictiva. El problema es que cuando sea el cambio de horario real, tendremos que mover a mano nuevamente la configuración horaria.

La opción 2 es adecuada, pero a veces no es posible. Hay aplicaciones que dependen de una versión particular de java y no es posible actualizar, en otros casos Oracle no ha liberado la actualización para la zona horaria.

La opción 3 puede ser útil en casos que no se pueda actualizar. La información de zona horaria es compatible entre diferentes versiones de Java.

La información de zona horaria se encuentra en:

JAVA_HOME/lib/zi

Por lo tanto es posible sobreescribir la informacion de zona horaria con la de una versión actualizada.

Por ejemplo, puedo sobreescribir el directorio 'zi' de una version de Java Sun 1.4 con el directorio 'zi' de una versión de OpenJDK actualizado. Con esto la información de zona horaria se actualizará y la máquina virtual mostrará la información correcta.

En sistemas UNIX puede usarse un enlace simbólico a una versión que sabemos se mantiene constantemente actualizada y asi incluso nos evitaremos hacer actualizaciones a mano.

Opciones y soluciones hay... la proxima vez no tendremos problemas con el cambio de horario.


bytes!

2 comentarios:

Christian González dijo...

¡Muchas gracias! Llevaba un buen rato peleando con algunas aplicaciones Java y despotricando contra Oracle por no dejar disponible el tzupdater, pero con esta solución ya me doy por satisfecho :-).

Leopard dijo...

Gracias por tu comentario.

Lo peor es que la informacion de ZI esta en formato binario. Quiza alguien más diestro en el tiema pueda publicar como crear nuestros propios archivos de zona horaria, que eso sería una gran solución.

Saludos.