¿Deben el servidor o el cliente manejar la zona horaria al enviar / recibir fechas?

Entiendo que la mejor práctica es almacenar las fechas / horas UTC en nuestra base de datos y mostrarlas al usuario en su zona horaria local. Almacenaremos la zona horaria en lugar de la compensación para que podamos admitir el horario de verano.

¿Cuál es la mejor manera de manejar zonas horarias?

Opción 1: el servidor habla solo UTC y el cliente se convierte en zona horaria

Todas las fechas enviadas al navegador en HTML están en UTC. El lado del cliente convertirá la hora UTC a la zona horaria correcta utilizando moment.js o similar. La zona horaria especificada en nuestra base de datos se usaría en lugar de la hora local del navegador, ya que puede ser incorrecta.

Cuando el usuario envía una fecha u hora, primero se debe convertir a una hora UTC antes de enviarse al servidor.

Opción 2: el servidor se convierte a zona horaria

Todos los cálculos todavía se realizan en UTC y la fecha / hora se convierten a la zona horaria correcta en el último momento posible, por ejemplo, al generar la fecha en HTML.

Cuando el cliente envía cualquier fecha / hora, debe convertirse inmediatamente a UTC.

¿Hay otra manera?

Cualquiera de las opciones es válida, pero hay ventajas y desventajas de cada enfoque. Hay varias cosas a considerar:

  • La conversión de la zona horaria nativa de JavaScript está limitada a la zona horaria local de la máquina en la que se está ejecutando, y también está gravemente dañada . Si planea convertir valores en el cliente, necesitará una de las bibliotecas de zona horaria enumeradas aquí . Personalmente recomiendo el momento-zona horaria .

  • La conversión de valores en el cliente (con cualquier biblioteca) requerirá datos de zona horaria, lo que puede ser algo grande si se quiere admitir todas las zonas horarias del mundo. Es posible que desee considerar limitar los datos al subconjunto mínimo que cumpla con sus requisitos.

  • La conversión de zona horaria del lado del servidor también requiere datos de zona horaria válidos. PHP tiene esto incorporado, y puede mantenerse actualizado con las actualizaciones del paquete timezonedb en PECL .

  • También ha etiquetado su pregunta con ASP.Net. .Net incluye TimeZoneInfo , que ofrece compatibilidad solo con las zonas horarias de Microsoft. Si desea las zonas horarias estándar de la IANA (como las que se usan en PHP), necesitará una biblioteca. Recomiendo Noda Time . Puede leer más sobre los diferentes tipos de zonas horarias en la etiqueta de la zona horaria .

  • Cómo entregar el resultado final depende de qué tipo de aplicación está escribiendo.

    • Si está creando una página web “tradicional”, donde el HTML se representa del lado del servidor, entonces estará renderizando una cadena legible. Eso significa comprender no solo la zona horaria, sino también la configuración regional del usuario para que pueda utilizar un formato culturalmente apropiado.

      Esto no está en absoluto vinculado a la zona horaria. Por ejemplo, puede ser estadounidense y usar el formato MM / DD / YYYY, pero aun así estar físicamente ubicado en Europa y usar una zona horaria europea.

    • Si su servidor entrega resultados a través de una API (es decir, JSON, XML, etc.), entonces sus resultados deben ser legibles por una máquina. Preferiblemente, debería utilizar el formato ISO 8601 . Específicamente, las marcas de tiempo deben entregarse como se describe en RFC 3339 .

      Esto significa que siempre deben incluir una Z (para valores UTC) o una compensación (para valores locales). Por lo tanto, puede tomar en cuenta la zona horaria del usuario, pero el resultado que entregue debe incluir el desplazamiento local para que no sea ambiguo.

      Por ejemplo, tiene el valor UTC 2014-07-09T12:00:00Z , luego en America/Los_Angeles es 2014-07-09T05:00:00-07:00 y eso es lo que se debe entregar a través de la API.

      En el lado del cliente, puede representar ese valor para el usuario con una biblioteca como moment.js . Por ejemplo:

       var s = moment.parseZone("2014-07-09T05:00:00-07:00").format("LLL"); 

Relacionados: ¿Cómo trabajar correctamente con Timezone?