Meu servidor de desenvolvimento local está no Oriente Médio, mas meu servidor de produção está no Reino Unido.
Eu preciso mostrar a data para o usuário em seu fuso horário. Por exemplo, se um usuário estiver na Arábia Saudita, preciso mostrar a hora de acordo com o formato da Arábia Saudita.
Devo criar uma nova tabela de banco de dados chamada TimeZone e salvar a hora em UTC?
Não há solução rápida para isso, infelizmente. A internacionalização de um aplicativo deve fazer parte das primeiras discussões de design, pois realmente vai ao centro de muitas áreas diferentes, incluindo comparações de data/hora e formatação de saída.
De qualquer forma, para entrar no caminho certo, é essencial armazenar as informações de fuso horário com a hora . Em outras palavras, perceber que a data/hora não
20130407 14:50
tem sentido sem (a) incluir o deslocamento UTC atual do fuso horário (nota 1) ou (b) garantir que toda a lógica que insere esses valores primeiro seja convertida em um certo deslocamento fixo ( provavelmente 0). Sem nenhuma dessas coisas, dois valores de tempo fornecidos são incomparáveis e os dados estão corrompidos . (O último método é brincar com fogo (nota 2) , a propósito; não faça isso.)No SQL Server 2008+, você pode armazenar o deslocamento com a hora diretamente usando o
datetimeoffset
tipo de dados. (Para completar, em 2005 e antes, eu adicionaria uma segunda coluna para armazenar o valor de deslocamento UTC atual (em minutos).)Isso facilita para um aplicativo do tipo desktop, pois essas plataformas normalmente possuem mecanismos para converter automaticamente uma data/hora + fuso horário para um horário local e depois formatar para saída, tudo com base nas configurações regionais do usuário.
Para a web, que é uma arquitetura inerentemente desconectada, mesmo com os dados de back-end configurados corretamente, é mais complexo porque você precisa de informações sobre o cliente para poder fazer a conversão e/ou formatação. Isso geralmente é feito por meio das configurações de preferência do usuário (o aplicativo converte/formata as coisas antes da saída) ou simplesmente mostrando as coisas com o mesmo formato fixo e deslocamento de fuso horário para todos (que é o que a plataforma Stack Exchange faz atualmente).
Você pode ver como, se os dados de back-end não estiverem configurados corretamente, muito rapidamente eles ficarão complicados e complicados. Eu não recomendaria seguir nenhum desses caminhos, porque você acabará com mais problemas no futuro.
Nota 1:
O deslocamento UTC de um fuso horário não é fixo: considere o horário de verão em que o deslocamento UTC de uma zona varia em mais ou menos uma hora. Além disso, as datas de verão das zonas variam regularmente. Portanto, usar
datetimeoffset
(ou uma composição delocal time
eUTC offset at that time
) resulta em recuperação máxima de informações.Nota 2:
Trata-se de controlar as entradas de dados. Embora não haja uma maneira infalível de validar os valores recebidos, é melhor aplicar um padrão simples que não envolva cálculos. Se uma API pública espera um tipo de dados que inclua um deslocamento, esse requisito ficará claro para o chamador.
Se não for esse o caso, o chamador tem que confiar na documentação (se ele a ler), ou o cálculo é feito incorretamente, etc. Há menos modos de falha/bug ao exigir um deslocamento, em particular para um sistema distribuído ( ou mesmo apenas web/banco de dados em servidores separados como o caso aqui).
Armazenar a compensação de qualquer maneira mata dois coelhos com uma cajadada só; e mesmo que isso não seja necessário agora , ele disponibiliza a possibilidade mais tarde, se necessário. É verdade que ocupa mais armazenamento, mas acho que vale a pena trocar porque os dados são perdidos se nunca forem gravados.
Desenvolvi uma solução abrangente para conversão de fuso horário no SQL Server. Consulte Suporte a fuso horário do SQL Server no GitHub .
Ele lida adequadamente com conversões entre fusos horários e de e para UTC, incluindo o horário de verão.
É semelhante em conceito à solução "T-SQL Toolbox" descrita na resposta do adss, mas usa os fusos horários IANA / Olson / TZDB mais comuns em vez dos da Microsoft e inclui utilitários para manter os dados mantidos como novas versões do TZDB sai.
Exemplo de uso (para responder ao OP):
Consulte o leia-me no GitHub para APIs adicionais e explicações detalhadas.
Além disso, observe que, como esta é uma solução baseada em UDF, ela não foi projetada com o desempenho como objetivo principal. Ainda seria melhor se essa funcionalidade fosse incorporada ao SQL Server, da mesma forma que a
CONVERT_TZ
função existe no Oracle e no MySQL.O SQL Server fez modificações em 2005 em diante, onde o fuso horário interno é salvo em UTC. Isso ocorreu em grande parte devido à replicação geográfica e aos projetores de alta disponibilidade envolvendo envio de logs, e ter os tempos de envio de logs salvos em fusos horários diferentes impossibilitava que o método antigo os restaurasse.
Assim, salvar tudo internamente no horário UTC permitiu que o SQL Server funcionasse bem globalmente. Esta é uma das razões pelas quais o horário de verão é um pouco difícil de lidar no Windows, porque outros produtos da MS, como o Outlook, também salvam a data/hora internamente como UTC e criam um deslocamento que precisa ser corrigido.
Eu trabalho em uma empresa onde temos milhares de servidores (mas não MS SQL Servers, mas todos os tipos de servidores) espalhados por todo o mundo, e se não forçássemos especificamente tudo para o UTC, todos enlouqueceríamos muito rapidamente.
Desenvolvi e publiquei o projeto “T-SQL Toolbox” no codeplex para ajudar qualquer pessoa que tenha dificuldades com manipulação de data e hora e fuso horário no SQL Server. É de código aberto e totalmente gratuito para usar.
Ele oferece UDFs de conversão de data e hora fáceis usando T-SQL simples com tabelas de configuração adicionais prontas para uso.
No seu exemplo, você pode usar o seguinte exemplo:
Isso retornará o valor de data e hora convertido para seu usuário.
Uma lista de todos os fusos horários com suporte pode ser encontrada na tabela "DateTimeUtil.Timezone" também fornecida no banco de dados T-SQL Toolbox.
Posso estar faltando algo óbvio, mas se tudo o que você quer fazer é exibir a data usando o fuso horário do usuário e o formato de idioma, a maneira mais simples é sempre armazenar as datas em UTC no banco de dados e deixar o aplicativo cliente converter de UTC para local fuso horário e use as configurações regionais do usuário para formatar a data de acordo.
Desde o Sql Server 2016, introduziu AT TIME ZONE , que permite converter um timeoffset que você pode especificar, como
Esta postagem do blog mostra todas as zonas (a partir de 2018):
Datas e horas no SQL Server: AT TIME ZONE - DZone Database
um pouco tarde, mas para mim resolvi mapeando entre janelas e banco de dados de fuso horário.
o seguinte resultado SQL é um mapeamento. Há um nome de coluna SQL_Names aplicar uma junção com a tabela [sys].[Time_Zone_Info] para obter detalhes do SQL Time Zone abaixo é a amostra.
Nota: o JSON não está cobrindo todo o fuso horário devido aos limites de caracteres aqui, mas você pode importar uma lista completa dos links abaixo.
Tente:
além disso, consulte os links abaixo:
Lista de fusos horários do banco de dados tz
Fuso horário do Windows