Como trabalhar com fusos horários no ASP.NET?

Eu estou trabalhando em um projeto “sistema de lembrete on-line” (ASP.NET 2.0 (C #) / SQL Server 2005)

Como este é um serviço de lembrete que irá enviar o email para os usuários em datas específicas. Mas o problema é que os usuários não são de países específicos, eles são de todo o mundo e de diferentes fusos horários. Agora, quando estou me registrando, estou solicitando o fuso horário dos usuários da mesma forma que o Windows pergunta ao nosso fuso horário no momento da instalação.

Mas eu não estou recebendo o se o usuário selecionou (+5,30) ou algo como fuso horário, em seguida, como lidar com esse fuso horário no meu aplicativo asp.net. Como trabalhar de acordo com o fuso horário.

E por favor, sugira se existe alguma maneira melhor de lidar com fusos horários nesta aplicação?

obrigado

A primeira coisa é certificar-se de que fuso horário seus dados estão dentro Eu recomendaria certificar-se de que qualquer DateTime que você armazene, seja armazenado na hora UTC (use o DateTime.ToUniversalTime() para se apossar dele).

Quando você for armazenar um lembrete para um usuário, precisará da hora UTC atual, adicionar ou remover a diferença de fuso horário do usuário e converter essa nova hora novamente em UTC; isso é o que você deseja armazenar no database.

Então, quando você quiser verificar se há lembretes para enviar, basta procurar no database por lembretes para enviar agora, de acordo com a hora UTC; essencialmente obter todos os lembretes que têm um carimbo de hora que é antes de DateTime.Now.ToUniversalTime() .

Atualize com alguns detalhes da implementação: Você pode obter uma lista de fusos horários do método TimeZoneInfo.GetSystemTimeZones() ; você pode usá-los para mostrar uma lista de fusos horários para o usuário. Se você armazenar a propriedade Id do fuso horário selecionado, poderá criar uma ocorrência de class TimeZoneInfo e calcular a hora UTC para um determinado valor de data / hora local:

 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); 

Eu recomendaria sempre usar o horário UTC (GMT) no lado do servidor (em code-behind, database, etc) e converter o tempo de UTC em hora local somente para fins de exibição . Isso significa que todas as manipulações de tempo – incluindo a economia de tempo no database, a execução de cálculos, etc – devem ser feitas usando o UTC.

O problema é: como o seu code-behind sabe qual é o fuso horário do navegador do cliente? Digamos que o usuário insira algum valor de data / hora (como 12/30/2009 14:30 ) no formulário e o envie para o servidor. Supondo que o usuário enviou a hora local, como o servidor sabe como converter esse valor para UTC?

O aplicativo pode solicitar que o usuário especifique o fuso horário (e salve-o em um cookie ou database persistente), mas isso exige um esforço extra do usuário, e seu aplicativo precisaria implementar a lógica e as canvass para isso. Seria melhor se o aplicativo pudesse determinar o fuso horário do cliente automaticamente .

Eu resolvi esse problema com a ajuda da function getTimezoneOffset do JavaScript, que é a única API que pode informar ao servidor sobre a diferença de horário entre a hora local no cliente e o GMT. Como essa é uma API do lado do cliente, fiz o seguinte: no lado do servidor, verifique se há um cookie de session personalizado mantendo o valor de compensação de tempo e, se não estiver disponível, recarregue a página (somente durante as chamadas GET e não POST) com alguma lógica JavaScript adicionada para gerar o deslocamento de tempo e salvá-lo no cookie. Do lado do cliente, isso é quase transparente (uma vez durante a session, eu recarrego uma página no GET). Depois de ter o deslocamento no cookie, aplico-o às funções de gerenciamento de tempo, dependendo da direção da conversão de hora (UTC para a hora local ou hora local para UTC).

Isso pode soar um pouco complicado, e é, mas depois de escrever funções auxiliares, integrar esse recurso no site foi uma questão de fazer uma única chamada em Page_Load (de páginas que precisavam de conversão de tempo) e usar rotinas de conversão de tempo ao enviar e recuperar valores de hora para e do navegador. Aqui está um exemplo de como ele pode ser usado:

 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, ...); ... } } ... } 

Se precisar de mais detalhes, confira o artigo É sobre o tempo: localizando o tempo em aplicativos ASP.NET (desculpe, mas não tenho um link direto para o artigo no site do editor, pois o asp.netPRO restringe o access apenas aos assinantes pagos existem links para cópias em PDF, no entanto). Eu gostaria de poder postar a amostra do artigo, mas não quero violar os direitos autorais; entretanto, aqui está um projeto para construir uma biblioteca de ajuda que tenha toda a funcionalidade e documentação necessárias (apenas ignore as coisas que você não precisa).

ATUALIZAÇÃO: O artigo foi publicado on-line com um projeto de amostra pelo novo editor aqui .

O problema com todas as respostas até agora é que elas não levam em conta o que Prashant está tentando alcançar. Se o usuário de seu sistema no dia anterior à mudança de horário de verão tiver um deslocamento de +12 e definir um lembrete para o dia seguinte, seu deslocamento quando o lembrete for acionado será +13 em vez disso.

É por isso que você só pode usar a compensação atual para algo que está acontecendo agora. Embora eu concorde com todos os outros que todas as vezes do lado do servidor (exceto possivelmente aqueles usados ​​apenas para exibição) devem ser armazenados em UTC.

Você pode querer olhar usando a estrutura DateTimeOffset em vez do DateTime se você estiver no framework 2.0 ou posterior.

O DateTimeOffset representa um ponto no tempo relativo ao horário UTC, portanto, deve ser mais fácil trabalhar neste caso.

Existem 2 etapas:

  • Detectar fuso horário diferente no lado do cliente usando JavaScript:

     var dt = new Date(); var diffInMinutes = -dt.getTimezoneOffset(); 
  • Em seguida, no lado do servidor, o código C # para converter o horário do servidor para o horário do cliente com base no deslocamento do fuso horário detectado acima:

————————;

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

Basicamente, tudo o que você precisa fazer é adicionar o deslocamento (horas + minutos) à hora local que o usuário inseriu. Adicionando o deslocamento basicamente dá-lhe um DateTime no fuso horário UTC (basicamente GMT).

Geralmente, é mais fácil padronizar todos os seus horários para o UTC, para que a lógica do aplicativo não precise lidar com os deslocamentos.

Esta página tem alguns bons exemplos: http://msdn.microsoft.com/en-us/library/bb546099.aspx

A questão é que o deslocamento da UTC varia em diferentes momentos do ano – cada fuso horário tem suas próprias regras. (Aprendi isso da maneira mais difícil ao desenvolver o aplicativo de agendamento de sala de reunião).

Parece que há suporte interno aqui: http://msdn.microsoft.com/pt-br/library/system.timezoneinfo.converttime.aspx

Não tentei por mim mesmo, mas parece prometer a conversão correta, respondendo pelo horário de verão.

Se não, aqui está uma ferramenta comercial (cara) que usei: http://www.worldtimeserver.com/time_zone_guide/