Convertir fechas y husos horarios en Java

Escrito por el , actualizado el .
java planeta-codigo programacion
Enlace permanente Comentarios

Java

Aunque en muchas aplicaciones no será necesario si desarrollamos una aplicación que trabaje con diferentes países y fechas probablemente deberemos tener en cuenta múltiples husos horarios o zonas horarias. Según estos husos horarios, por ejemplo, en el momento que son las 12:00 en Madrid hora local no son las 12:00 en Buenos Aires, si dos ciudades emplean diferente huso horario hay que tenerlo en cuenta para obtener la hora local en cada ciudad.

Hasta la versión 7 de Java el trabajo con fechas era complicado con las clases proporcionadas GregorianCalendar y Date, una alternativa a la API de Java para el manejo de fechas hasta esta versión era emplear la librería JodaTime. JodaTime ofrece una API mejor y más completa para el manejo de fechas hasta la versión de Java 7. Con la nueva API para fechas de Java 8, entre otras novedades incluídas, la situación ha mejorado pero hasta que tengamos oportunidad de usar esta versión puede que pase bastante tiempo y sigamos obligados a usar JodaTime si tenemos posibilidad de usar esta librería o usar directamente la API de Java 7 si no podemos.

Otro aspecto que debemos tener en cuenta en una aplicación es en que huso horario vamos a guardar las fechas en la base de datos, para simplificar lo recomendable es guardar siempre las fechas en el mismo huso horario. Podemos elegir cualquier huso horario quizá la local del lugar donde estamos o una mas genérica como UTC.

Podemos convertir la fecha de un huso horario a otro ya sea usando JodaTime, Java 7 o Java 8, por ejemplo ¿si en Madrid (España) son las 12:00 que hora sería en ese momento en Buenos Aires (Argentina)? El código que podemos emplear en Java para cambiar de zona horaria y averiguarlo es el siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package io.github.picodotdev.timezone;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

public class Main {

	public static void main(String[] args) {
		// JodaTime
		{
			DateTime fecha = new DateTime(2015, 1, 31, 12, 00, DateTimeZone.forID("Europe/Madrid"));

			System.out.println("JodaTime");
			System.out.printf("Hora Madrid:\t\t %s\n", fecha);
			System.out.printf("Hora Buenos Aires:\t %s\n", fecha.withZone(DateTimeZone.forID("America/Argentina/Buenos_Aires")));
		}
		
		// Java 8
		{
			ZonedDateTime fecha = ZonedDateTime.of(2015, 1, 31, 12, 00, 00, 00, ZoneId.of("Europe/Madrid"));

			System.out.println("\nJava 8");
			System.out.printf("Hora Madrid:\t\t %s\n", fecha);
			System.out.printf("Hora Buenos Aires:\t %s\n", fecha.withZoneSameInstant(ZoneId.of("America/Argentina/Buenos_Aires")));			
		}

		// Java 7
		{
			Calendar calendar = new GregorianCalendar();
			calendar.set(2015, 0, 31, 12, 0, 0);

			SimpleDateFormat sdfMadrid = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
			sdfMadrid.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));

			SimpleDateFormat sdfArgentina = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
			sdfArgentina.setTimeZone(TimeZone.getTimeZone("America/Argentina/Buenos_Aires"));

			System.out.println("\nJava 7");
			System.out.printf("Hora Madrid:\t\t %s\n", sdfMadrid.format(calendar.getTime()));
			System.out.printf("Hora Buenos Aires:\t %s\n", sdfArgentina.format(calendar.getTime()));
		}
	}
}
Main.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
JodaTime
Hora Madrid:		 2015-01-31T12:00:00.000+01:00
Hora Buenos Aires:	 2015-01-31T08:00:00.000-03:00

Java 8
Hora Madrid:		 2015-01-31T12:00+01:00[Europe/Madrid]
Hora Buenos Aires:	 2015-01-31T08:00-03:00[America/Argentina/Buenos_Aires]

Java 7
Hora Madrid:		 2015-01-31T12:00:00+01:00
Hora Buenos Aires:	 2015-01-31T08:00:00-03:00
output.txt

Java 7 requiere unas pocas líneas de código fuente más y en este caso se hace usando un SimpleDateFormat, en el caso de JodaTime y Java 8 el código es bastante similar.

El huso horario de Madrid es Europe/Madrid y el huso horario de Buenos Aires es America/Argentina/Buenos_Aires en el momento de escribir este artículo Madrid tiene un desplazamiento respecto a UTC de +01:00 y Buenos Aires de -03:00 con lo que entre estas dos ciudades hay una diferencia de cuatro horas en tiempo local. Quizá nos interese conocer el tiempo local actual en una ciudad y con el conversor entre husos horarios podemos comprobar que hemos programado correctamente la conversión en código.

Finalmente, hay que tener en cuenta que los horarios de verano que se establecen en cada país con la intención de ajustar normalmente el horario a las horas de luz y de este modo ahorrar energía. Estos horarios de verano los establece cada país y varían más a menudo de lo que podemos creer, a veces son una cuestión política. En el JDK para actualizar estos horarios de verano debemos actualizar el JDK esperando que Oracle los haya actualizado debidamente o usar la herramienta Timezone Updater Tool. El actualizar el JDK o usar la herramienta Timezone Updater Tool en un servidor para esto puede ser un problema o simplemente es algo que no controlamos como desarrolladores de la aplicación por no estar el servidor bajo nuestro control, esta es otra ventaja de usar JodaTime ya que esta librería como dependencia del proyecto si está bajo nuestro control y podemos ir actualizando la versión de la misma en la que los horarios de verano si están actualizados.


Comparte el artículo: