Zonas horarias en Blazor

Estoy desarrollando un proyecto personal en Blazor WASM .NET 5 en un equipo Mac con procesador M1, y como todo camino de aprendizaje, lleva algo de tiempo resolver ciertas cosas. No es descubrir el hilo negro, pero hacerlo desde cero implica un esfuerzo adicional.

Este es mi primer blog y nace con la idea de compartir mi camino en la búsqueda de soluciones con Blazor para ayudar a que otros con las mismas dudas.

Los temas que considero importantes para implementar Zonas Horarias en una Aplicación Web son las siguientes:

  • ¿Cuando implementar zonas horarias?
  • Conceptos básicos de zonas horarias en una aplicación web Blazor WASM
  • Implementar que el usuario establezca su zona horaria
  • Como guardar fechas en la base de datos
  • Como mostrar fechas y horas al usuario en su zona horaria

¿Cuando implementar zonas horarias?

Aunque esta respuesta parezca obvia, es bueno considerar lo siguiente:

  • La principal, si los usuarios a los que esta destinada la aplicación están fisicamente en tú país en distinto horario, aunque al final si se trata de una aplicación para uso interno de una compañía podría no significar tanto que las fechas y horas del sistema siempre se apliquen a la hora de las oficinas centrales.
  • Que tu aplicación pueda ser usada por personas de otro país. En este caso, también deberías considerar implementar información regional como Idioma, moneda, formato de fechas etc. Pero sería tema para otro articulo.
  • Ahora que si ninguna de las dos anteriores aplica, podía ser importante que incluyas esta funcionalidad a tu aplicación por que en un futuro podría ser un requermiento que ya tendrías resuelto. Pensando en que cada vez es más usado el home office eso sería suficiente para que todas las aplicaciones incluyeran las zonas horarias en el perfil de los usuarios.

Conceptos básicos de zonas horarias en una aplicación web Blazor WASM

Nombres de las zonas horarias

Es un tema muy importante, por que en Windows los nombres (o ID's) de las zonas lucen algo como esto:

  • Pacific Standard Time

Mientras en otros entornos no Windows tendríamos que considerar los nombres o ID's de las zonas horarias del IANA Internet Assigned Numbers Authority.Que lucen algo como esto para la misma zona de Windows para Pacific Standard Time.

  • America/Los_Angeles

Luego entonces la pregunta es que Standard usar ¿Windows o IANA?. Algo importante es que las zonas horarias de windows están agrupadas, ya que una zona horaria de windows puede corresponder a varias zonas horarias de IANA, hay funciones de .NET para resolver esto, como lo explica en un excelente articulo Rick Strahl , pero lo ideal seria evitar estos lios.

En mi caso elegí utilizar los nombre de Windows aunque uso Mac. No podré obtener los nombres de forma automática (por el momento). Es decir tendré que meter a mano los nombres de las zonas o generar un archivo Json. El problema es que al utilizar el método TimeZoneInfo.GetSystemTimeZones() de .NET en una Mac, no se obtiene "por el momento" los nombres de las zonas o se obtienen incompletas. Aun no sé a que se debe el error, mientras tanto el archivo Json resuelve de manera temporal este asunto.

Horarios de verano

Si utilizas el método GetSystemTimeZones() o un archivo Json actualizado descargado de IANA. La ventaja es que ya incluyen información de los horarios de verano de cada zona. Solo tendrías que validar la fecha de inicio y final para determinar si aplicas el horario de verano o no.

Implementar que el usuario establezca su zona horaria

Debes considerar implementar que se pueda establecer la zona horaria "predeterminada" para la aplicación y luego también que el usuario pueda establecer la zona horaria para él en particular, para que se guarde en sus datos de perfil. Es decir, que si el usuario no establece su zona horaria, se utilice por defecto la establecida para la aplicación.

Como guardar fechas en la base de datos

Como buena practica las fechas de los eventos o datos que se generan de la aplicación si se implementa el uso de zonas horarias, deberían almacenarse en Coordinated Universal Time (UTC), para que luego cuando se consulte esa información y se muestre al usuario, se convierta a su zona horaria. Ej. Si en la Ciudad de México son las 15:00 hrs. esa seria la hora en mi zona horaria, pero al guardarse en la base de datos se guardaría como 21:00 hrs. ya que mi zona horaria es UTC-06:00.

Para esto hay funciones de .NET que lo hacen por nosotros. solo debemos indicarle que una fecha valida la queremos convertir a "Hora Universal".

DateTime localDateTime = DateTime.Now;
univDateTime = myLocalTime.ToUniversalTime();
Console.WriteLine("{0} hora local {1} hora universal.", localDateTime, univDateTime);

//     Resultado
//     21/06/2021 3:18:00 PM hora local 21/06/2021 9:18:00 PM universal time.

En este caso la fecha que debes guardar en la Hola buen día es la que contiene univDateTime

Como mostrar fechas y horas al usuario en su zona horaria

Cuando se recuperan los datos de la Hola buen día para mostrarlo al usuario en la zona configurada realizamos lo siguiente.

Suponiendo que la zona configurada del usuario es : "Pacific Standard Time" almacenado en la variable "tzUser" o en su caso como campo del perfil del usuario, y la hora del evento almacenado en Universal Time en la variable dateDB.

DateTime dateDb = EventoDB;
tzUser = "Pacific Standard Time";
TimeZoneInfo tzInfo = TimeZoneInfo.FindSystemTimeZoneById(tzUser);
Console.WriteLine(TimeZoneInfo.ConvertTimeToUtc(dateDb, tz));

Conclusiones

Con esto espero tengas una idea más clara de cómo implementar Zonas horarias en tu aplicación Blazor. Cualquier comentario es bienvenido.