Zonas horarias, DST, Desplazamientos y otras zarandajas

Ir a la parte 1 de 2: “Sobre la Hora Universal y los relojes atómicos (o qué tienen en común el TomTom y unos trigales)” ]

Continuamos desentrañando el misterio de las horas, orientando la explicación principalmente a programadores.

Hemos establecido qué sistemas de medición de la hora existen. También hemos visto que el estandard de facto es UTC, y por buenas razones.

Y ahora vamos a ver como se pueden representar esas horas en una aplicación.

A efectos prácticos, en este artículo voy a llamar “hora” al conjunto de “fecha+hora“.

 

Conceptos básicos

Repaso de UTC

Quedabamos en que UTC es una hora universal, que trata de indicar la hora del planeta Tierra en general. No está ligado a ningún país en concreto, ni a ningún continente, sino al planeta entero: España no tiene horas UTC. Argentina no tiene horas UTC. El planeta Tierra sí que tiene horas UTC.

Si en una hora UTC particular es pleno día en España, entonces en esa misma hora UTC será noche cerrada en sus antípodas; y será el amanecer o el anochecer si nos quedamos a medio camino entre ambos puntos.

UTC no sufre saltos [*], sino que avanza siempre a una velocidad constante. Porque el planeta Tierra tampoco sufre saltos ni rotaciones bruscas en ningún momento (menos mal :-D).
[*] Técnicamente sí (tiene saltos por debajo del segundo), pero se puede ignorar perfectamente para este artículo.

 

Hora Local (Local Time)

Los habitantes de este planeta estamos acostumbrados a hablar en términos locales. Yo, como habitante de Madrid, puedo decir “Me levanto a trabajar a las 07:00”. Un japonés, a su vez, puede decir “Yo también me levanto a trabajar a las 07:00”. Pero obviamente no hablamos de la misma hora UTC, sino de una hora “local”.

Trabajar con horas locales puede ser complicado, por ejemplo cuando el locutor se desplaza de sitio. Si despegas de Madrid a las 10:00 (hora local madrileña), vuelas 10 horas, y aterrizas en Miami, la hora local de Miami no serán las 20:00, sino otra, que hay que calcular en base a unos cuantos factores.

En cambio, si despegas a las 10:00 UTC, que aterrizas a las 20:00 UTC.

Desplazamiento (Offset)

El offset es, literalmente, la siguiente resta matemática: hora localhora UTC.

Por ejemplo: La hora local actual en Madrid es finales de Enero a las 20:00. La hora UTC actual en el planeta es finales de Enero a las 19:00 UTC. Por tanto, 20:00 – 19:00 = 01:00 de offset.

Inciso sobre el Horario de Verano:

El Horario de Verano, como sabeis, tiene como objetivo reducir el consumo eléctrico, tener más luz durante las horas laborales, etc (al margen de que se consigan o no dichos propósitos :-P).

Consiste en mover las manecillas de los relojes locales de un país, para atrasar o adelantar la hora local durante unos meses determinados, cada año.

  • Lo típico es atrasar o adelantarlo 1h, pero en algunos paises es 30 minutos.
  • Cada país lo puede aplicar durante unos meses diferentes: de marzo a octubre, de abril a septiembre… Los días exactos también pueden variar.
  • En muchos países ni siquiera se aplica el Horario de Verano.

En cualquier caso, el offset ya lleva incluído el horario de verano cuando se usa, puesto que el offset se obtiene restando la hora local (que ya lleva aplicado el cambio horario) y la hora UTC.

Otro ejemplo: En Agosto de este año se habrá aplicado el horario de verano en Madrid, por lo que el offset no será 01:00h sino 02:00h.

El offset de una localización geográfica puede variar tanto a lo largo de un mismo año, como hemos visto, pero también a lo largo de varios años. Por ejemplo:

  • Antes del 1901, cada provincia española tenía su propia hora local, en base a su meridiano concreto. Ahora ya no.
  • En el 1918, en España se decide empezar a aplicar el horario de verano, que nunca antes se había utilizado. El offset ya no es el mismo todo el año, sino que aumenta 1h en verano (como en el presente).
  • El 16 de Marzo de 1940, España decide incrementar todos sus relojes en una hora: el offset pasa de 0h a 1h en invierno, y de 1h a 2h en verano. (se ha cambiado la zona horaria, que explico más abajo)
  • Si varios paises con diferentes horas locales eliminan sus fronteras políticas para unirse en un solo país, seguramente modifiquen sus horas locales para coincidir en todo el territorio (variando por tanto el offset).

Por tanto, es perfectamente posible que dos países tengan el mismo offset durante algunos meses del año, pero difieran durante otros.

Dicho de otra forma: a partir de un offset, no se puede deducir en qué localización te encuentras, ni por tanto qué otros offsets existirán en otros momentos del año.

Por ejemplo: Si no sabes si tu +01:00h actual es de Madrid o del Congo, no puedes saber si en Agosto será un +02:00h (caso de Madrid), o se mantendrá en +01:00h (caso de Congo, sin horario de verano).

 

Zona horaria (Time Zone, o TZ)

Se dice que varias poblaciones están en una misma Zona Horaria, cuando desde el año 1970 han compartido siempre la misma hora local. La nomenclatura es “Area/Localización”.

Mapa de todos los TimeZones

No hay que confundir con los husos horarios, meridianos ni offsets. Son conceptos diferentes: “UTC+02:00” no es realmente una Zona Horaria, es un Offset respecto de UTC.

Por ejemplo: En España, desde el 1970 hasta ahora, han existido tres regiones que no siempre han compartido completamente las horas locales en todo momento. Las tres zonas horarias (o TZs) son:

  • Europe/Madrid: para la península y baleares principalmente.
  • Atlantic/Canary: para el archipiélago canario.
  • Africa/Ceuta: para Ceuta y Melilla.

Actualmente, esas 3 timezones usan horario de verano, por lo que actualmente sus offsets respectivos de invierno son 1h, 0h y 1h; y los de verano 2h, 1h y 2h.

Cada TZ ha tenido un pasado diferente: algunos aplicaron el horario de verano durante 20 años, otros no lo aplicaron; unos tenian un offset de 5h, otros de 10h, etc.

Toda esa información se almacena en lo que se llama tz database (en castellano, base de datos de zonas horarias).

La tz database debe ser actualizada constantemente, reflejando los cambios horarios que se pueden producir a lo largo de los años.

 

Empieza el meollo de la cuestión


Una vez que conocemos los conceptos básicos, podemos pasar a la acción:

¿En qué me influye todo eso a la hora de diseñar mi software?

¿Cómo gestiono las horas correctamente?
¿Y si mi usuario vuela de España a la India y cambia el reloj de su portatil?
¿Y si mi usuario quiere introducir la hora local de despegue y la hora local de aterrizaje en mi software de calendario?
¿Y si mi software tiene varios usuarios simultáneos en diferentes zonas del mundo?

Una política habitual en el mundo de la programación es:

Almacena y procesa globlamente, muestra localmente“.

Dicho de otra forma: elige un formato neutro para almacenar y operar sobre los datos, y preocúpate de las particularidades culturales cuando debas mostrar o recoger los datos de un usuario final.

Recordemos que en este post se usa la palabra “hora” como abreviación de “fecha+hora“.

 

“Almacena y procesa globalmente”

Empecemos con un ejemplo sencillote:

Tenemos una variable tipo entero, cuyo valor es 7 millones.
  • El ordenador almacena y opera globalmente. Concretamente, usa el binario: 00000000011010101100111111000000.
  • En cambio al mostrarlo en una hoja de cálculo, nos puede mostrar “7.000.000“, o bien “7,000,000“, o tal vez “7e6“, o incluso “######“, según el contexto local (dónde vivimos, tamaño de la celda, formato del número…).
De igual forma, la práctica apropiada suele ser almacenar y operar en Hora UTC, y mostrar en Hora Local.
Y no es porque sea conveniente, sino que muchas veces además es necesario. Por ejemplo:

Tenemos una Hora Local, las 15:00 de un día de Enero. Se le quiere sumar casi medio año (24h*180días=4320h) a esa hora. ¿Cuál será la Hora Local resultante?:

  1. Las 15:00 hora local, como en la hora de partida.
  2. Las 16:00 hora local, porque hay que aplicar el Horario de Verano.
  3. Ninguna de las 2 anteriores.
  4. Cualquiera de las 3 anteriores.

Y la solución es 4) Cualquiera de las tres anteriores, puesto que depende de la zona horaria:

  • En el Moscú actual o el Madrid del año 1910, no hay horario de verano, luego sería 1) Las 15:00.
  • En el Madrid actual hay horario de verano, luego sería 2) Las 16:00.
  • En la Isla de Lord Howe hay horario de verano de 30m, en vez de la hora típica, luego sería 3) Las 15:30.

Queda claro entonces que la única forma de operar correctamente con horas es pasarlas a UTC, operar sobre ellas y finalmente (si hace falta), convertirlas a la Hora Local de nuestra elección para mostrárselo al usuario final.

 

“Muestra localmente”

Hemos establecido que, para la interfaz con el usuario final, necesitamos conversiones de UTC a Hora Local (al renderizar en pantalla) y viceversa (al aceptar datos del usuario)

Si habéis entendido perfectamente todo lo explicado hasta hora, se pueden deducir cuáles son las posibles conversiones inequívocas que podemos hacer:

Para conseguir esto...:...puedes usar esto:
Hora LocalUTC con TZ del usuario
Hora LocalUTC con Offset del usuario en esa hora y lugar
UTCHora Local con Offset del usuario en esa hora/lugar
UTCHora Local con TZ del usuario -- Imposible
Dos aspectos a destacar son:

a) Almacenar el offset no vale para mucho

Un offset solamente es válido para una hora concreta del año, en un lugar concreto del planeta.
Tal y como se explicó antes, en la sección de Offset: si solamente conocemos el Offset para una Hora Local, no podemos averiguar mágicamente a qué lugar (TimeZone) pertenece esa Hora Local.
Y por tanto, tampoco podemos calcular automágicamente el offset que habrá en otros momentos del año (o lo que es lo mismo, la Hora Local en otros momentos del año). Para ello necesitamos el TZ; no queda otra opción posible.
Así que en vez de almacenar, Hora Local + Offset, bien podríamos almacenar únicamente el UTC a secas.

b) El usuario debería poder especificar el offset al introducir una hora

Como veis en la tabla, la unica forma inequívoca de que el usuario introduzca una hora, es indicar también el offset de alguna forma.
Por ejemplo: si el usuario introduce la Hora Local “02:30”, necesitamos saber a cuál de las dos posibles “02:30” existentes se refiere (en caso de existir horario de verano en ese lugar).
Existen muchas formas de hacerlo:
  • Un checkbox con el que marcar si la fecha va con DST o no.
  • Una dropdown con 25 o 23 elementos (horas), en vez de los 24 habituales.
  • Una mensaje de pregunta que únicamente saltará cuando se dé el caso de una hora ambigua.
  • Etc.
Por ejemplo, esta es una forma que aconseja Microsoft si se utiliza su framework de .NET:  MSDN – How to let users resolve ambiguous times

 

Si no se da esa opción al usuario, el sistema informático deberá resolver la ambigüedad de forma arbitraria. Que en función del caso concreto, puede ser algo perfectamente aceptable (aunque siempre mejorable).

Ultílogo

Con esto terminamos la segunda y última parte del temario.
Espero que hayais conseguido leer y entender hasta este punto, y no estéis aquí unicamente porque os haya llamado la atención eso de “ultílogo” ;-).
Con suerte el artículo ha sido de ayuda y os evitará bugs y quebraderos de cabeza en un futuro.

 

Happy coding!

Ir a la parte 1 de 2: “Sobre la Hora Universal y los relojes atómicos (o qué tienen en común el TomTom y unos trigales)” ]

Tags: , [es] | January 29th, 2012 |

4 Responses to “Zonas horarias, DST, Desplazamientos y otras zarandajas”

  1. stenyak.com » Blog Archive » Sobre la Hora Universal y los relojes atómicos (o qué tienen en común el TomTom y unos trigales) Says:

    […] (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })();Tweet[ Ir a la parte 2 de 2: "Zonas horarias, DST, Desplazamientos y otras zarandajas" ] […]

  2. crc Says:

    Muy interesante. Me gustaría hacer una puntualización muy sutil, y es que ¡UTC si salta! aunque a efectos práticos es como si no lo hiciese:

    http://es.wikipedia.org/wiki/Segundo_intercalar

  3. stenyak Says:

    Efectivamente crc, lo explico en la Parte 1 [*], pero voy a puntualizarlo para dejarlo más claro en este post.

    [*] http://www.stenyak.com/archives/1004/sobre-la-hora-universal-y-los-relojes-atomicos-o-que-tienen-en-comun-el-tomtom-y-unos-trigales/

  4. lopo lóbez Says:

    Muy didácticos e ilustrativos ambos blogs sobre el tiempo, muchas gracias.

    Por fin sabemos cómo es un cuásar!… 😉

Leave a Reply