¿Cómo trabajar con husos horarios en ASP.NET?

Estoy trabajando en un proyecto de “sistema de recordatorio en línea” (ASP.NET 2.0 (C #) / SQL Server 2005)

Como se trata de un servicio recordatorio que enviará el correo a los usuarios en una fecha determinada. Pero el problema es que los usuarios no son de un país específico, sino de todo el mundo y de diferentes zonas horarias. Ahora, cuando me estoy registrando, pido la zona horaria de los usuarios de la misma manera que Windows pregunta por nuestra zona horaria en el momento de la instalación.

Pero no obtengo el si el usuario seleccionó (+5.30) o alguna zona horaria y luego cómo manejar esta zona horaria en mi aplicación asp.net. Cómo trabajar de acuerdo a la zona horaria

¿Y por favor sugiera si hay alguna forma mejor de manejar zonas horarias en esta aplicación?

Gracias

Lo primero es asegurarse de en qué zona horaria se encuentran sus datos. Recomiendo asegurarse de que cualquier DateTime que almacene esté almacenado en hora UTC (use DateTime.ToUniversalTime() para obtenerlo).

Cuando va a almacenar un recordatorio para un usuario, necesitará la hora UTC actual, agregar o eliminar la diferencia de zona horaria del usuario y convertir esa nueva hora a UTC; esto es lo que quiere almacenar en la base de datos.

Luego, cuando desee verificar el envío de recordatorios, simplemente debe buscar en la base de datos los recordatorios para enviar ahora, de acuerdo con la hora UTC; esencialmente obtienes todos los recordatorios que tienen una marca de tiempo que es anterior a DateTime.Now.ToUniversalTime() .

Actualice con algunas especificaciones de implementación: puede obtener una lista de zonas TimeZoneInfo.GetSystemTimeZones() método TimeZoneInfo.GetSystemTimeZones() ; puede usarlos para mostrar una lista de zonas horarias para el usuario. Si almacena la propiedad Id en la zona horaria seleccionada, puede crear una instancia de clase TimeZoneInfo y calcular la hora UTC para un valor de fecha / hora local determinado:

 TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(""); // May 7, 08:04:00 DateTime userDateTime = new DateTime(2009, 5, 7, 8, 4, 0); DateTime utcDateTime = userDateTime.Subtract(tzi.BaseUtcOffset); 

Yo recomendaría usar siempre el tiempo UTC (GMT) en el lado del servidor (en el código subyacente, la base de datos, etc.) y convertir el tiempo desde el UTC a la hora local para fines de visualización solamente. Esto significa que todas las manipulaciones de tiempo, incluido el ahorro de tiempo en la base de datos, la realización de cálculos, etc., deben realizarse con UTC.

El problema es: ¿cómo sabe el código subyacente cuál es la zona horaria del navegador del cliente? Supongamos que el usuario ingresa algún valor de fecha / hora (como 30/12/2009 a las 14:30 ) en el formulario y lo envía al servidor. Suponiendo que el usuario envió la hora local, ¿cómo sabe el servidor cómo convertir este valor en UTC?

La aplicación puede solicitar al usuario que especifique la zona horaria (y la guarde en una cookie o base de datos persistente), pero requiere un esfuerzo adicional del usuario, y su aplicación debería implementar la lógica y las pantallas para esto. Sería mejor si la aplicación pudiera determinar la zona horaria del cliente automáticamente .

He abordado este problema con la ayuda de la función getTimezoneOffset de JavaScript, que es la única API que le puede decir al servidor sobre la diferencia horaria entre la hora local en el cliente y GMT. Como esta es una API del lado del cliente, hice lo siguiente: en el servidor, compruebe si hay una cookie de sesión personalizada que contenga el valor de compensación de tiempo, y si no está disponible, vuelva a cargar la página (solo durante las llamadas GET y no POST) con alguna lógica de JavaScript agregada para generar el desplazamiento de tiempo y guardarlo en la cookie. Desde el lado del cliente esto es casi transparente (una vez durante la sesión, recargo una página en GET). Una vez que tengo el desplazamiento en la cookie, lo aplico a las funciones de gestión del tiempo dependiendo de la dirección de la conversión de tiempo (UTC a la hora local, o hora local a UTC).

Esto puede sonar un poco complicado, y lo es, pero después de escribir funciones auxiliares, integrar esta característica en el sitio era una cuestión de hacer una sola llamada en Page_Load (de páginas que necesitaban conversión de tiempo) y usar rutinas de conversión de tiempo al enviar y recuperar valores de tiempo hacia y desde el navegador. Aquí hay un ejemplo de cómo se puede usar:

 using My.Utilities.Web; ... // Derive the form class from BaseForm instead of Page. public class WebForm1: BaseForm { ... private void Page_Load(object sender, System.EventArgs e) { // If we only want to load the page to generate the time // zone offset cookie, we do not need to do anything else. if (InitializeLocalTime()) return; // Assume that txtStartDate is a TextBox control. if (!IsPostback) { // To display a date-time value, convert it from GMT (UTC) // to local time. DateTime startDate = GetStartDateFromDB(...); txtStartDate.Text = FormatLocalDate(startDate); ... } else { // To save a date-time value, convert it from local // time to GMT (UTC). DateTime tempDate = DateTime.Parse(txtStartDate.Text); DateTime startDate = ConvertLocalTimeToUtc(tempDate); SaveStartDateInDB(startDate, ...); ... } } ... } 

Si necesita más detalles, consulte el artículo It’s About Time: Localizing Time en ASP.NET Applications (lo siento, pero no tengo un enlace directo al artículo en el sitio del editor, ya que asp.netPRO restringe el acceso solo a los suscriptores pagos ; sin embargo, hay enlaces a copias en PDF). Me gustaría poder publicar la muestra del artículo, pero no quiero violar los derechos de autor; sin embargo, aquí hay un proyecto para construir una biblioteca de ayuda que tiene toda la funcionalidad y documentación necesarias (simplemente ignore las cosas que no necesita).

ACTUALIZACIÓN: el artículo ha sido publicado en línea con un proyecto de muestra por el nuevo editor aquí .

El problema con todas las respuestas hasta ahora es que no toman en cuenta lo que Prashant está tratando de lograr. Si el usuario de su sistema el día anterior al cambio de horario de verano tiene una compensación de +12 y establece un recordatorio para el día siguiente, su compensación cuando se supone que el recordatorio se activará será +13 en su lugar.

Es por eso que solo puedes usar el desplazamiento actual para algo que está sucediendo ahora. Aunque estoy de acuerdo con todos los demás en que todas las veces el lado del servidor (excepto posiblemente los que se usan solo para la visualización) deben almacenarse en UTC.

Puede utilizar la estructura DateTimeOffset en lugar de DateTime si está en framework 2.0 o posterior.

DateTimeOffset representa un punto en el tiempo relativo a la hora UTC, por lo que debería ser más fácil trabajar en este caso.

Hay 2 pasos:

  • Detecta diferentes zonas horarias en el lado del cliente usando Javascript:

     var dt = new Date(); var diffInMinutes = -dt.getTimezoneOffset(); 
  • Luego, en el lado del servidor, código C # para convertir la hora del servidor a la hora del cliente en función del desplazamiento de la zona horaria detectada anteriormente:

————————;

 string queryStr = Request.QueryString["diffInMinutes"]; int diffInMinutes = 0; if (Int32.TryParse(queryStr, out diffInMinutes)) { clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes); } 

Básicamente, todo lo que necesita hacer es agregar el desplazamiento (horas + minutos) a la hora local que ingresó el usuario. Agregar el desplazamiento básicamente te da un DateTime en la zona horaria UTC (básicamente GMT).

En general, es más fácil estandarizar todos sus tiempos en UTC, de modo que su lógica de aplicación no tenga que lidiar con los desplazamientos.

Esta página tiene algunos buenos ejemplos: http://msdn.microsoft.com/en-us/library/bb546099.aspx

El problema es que la compensación de UTC variará en diferentes momentos del año: cada zona horaria tiene sus propias reglas. (Lo aprendí de la peor manera al desarrollar la aplicación de progtwigción de sala de reuniones).

Parece que hay soporte integrado aquí: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

No lo he probado, pero parece prometer la conversión correcta, teniendo en cuenta los ahorros de luz diurna.

Si no, aquí hay una herramienta comercial (costosa) que he usado: http://www.worldtimeserver.com/time_zone_guide/