Cómo se debe trabajar con campos de fecha y hora en varias zonas horarias?

Cuando trabajamos en un proyecto geográficamente local, es posible que no nos hayamos topado con este inconveniente todavía, se maneja una sola zona horaria, el servidor está configurado en sincronía con la hora local, todos los datos se guardan con hora local, no hay ningún problema. Pero qué pasa cuando nuestro producto comienza a hacer usado por personas alrededor del mundo? Su hora local ya no es la misma que la hora en el servidor.

Si tenemos campos como fecha_creacion o fecha_actualizacion generalmente son del tipo DATETIME, y son auto-actualizados, cuando insertas un nuevo registro se creará con CURRENT_TIME() y cuando se actualiza podemos poner la fecha desde la aplicación o un trigger.

Si tenemos esta configuración, si un registro se creó a las 8 am hora local, la fecha_creacion que ve el usuario A en zona horaria local es 8am pero la fecha_creacion que ve el usuario B en una zona horaria de menos 2 horas de diferencia debería ser 6am, pero es 8am también. No estamos considerando en que zona horaria se encuentra el usuario B.

Ahora bien, podemos comenzar a capturar la zona horaria en las preferencias del usuario B, o reconocer en dónde se encuentra ubicado usando geoip. Y comenzar a realizar operaciones de transformación de fecha/hora entre zonas horarias, pero esto rapidamente se vuelve inmanejable. Las operaciones de cambio de zona horaria siempre son complicadas.

La mejor alternativa para solucionar este inconveniente es usar siempre una hora estandarizada UTC. Todas los campos fecha y hora deben estar guardados en UTC, la configuración de hora en los servidores de aplicación debe ser UTC, la configuración de la hora en el servidor de base de datos también debe ser UTC.

Esto permite que el despliegue de una fecha y hora a un usuario específico se convierta en un asunto pertinente solo a la interfaz de usuario, solo al mostrar información al usuario se cambia de UTC a la zona horaria escogida por el usuario.