Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Conversão de data e hora de fuso horário para fuso horário no sql server


Os carimbos de data e hora Unix são um número inteiro de segundos desde 1º de janeiro de 1970 UTC.

Assumindo que você quer dizer que tem uma coluna inteira em seu banco de dados com este número, então o fuso horário do seu servidor de banco de dados é irrelevante.

Primeiro converta o timestamp para um datetime modelo:
SELECT DATEADD(second, yourTimeStamp, '1970-01-01')

Este será o UTC datetime que corresponde ao seu carimbo de data/hora.

Então você precisa saber como ajustar esse valor ao seu fuso horário de destino. Em grande parte do mundo, uma única zona pode ter vários deslocamentos, devido ao horário de verão.

Infelizmente, o SQL Server não tem capacidade de trabalhar diretamente nos fusos horários de trabalho. Portanto, se você estivesse, por exemplo, usando o horário do Pacífico dos EUA, não teria como saber se deveria subtrair 7 horas ou 8 horas. Outros bancos de dados (Oracle, Postgres, MySql, etc.) têm maneiras internas de lidar com isso, mas o SQL Server não. Portanto, se você estiver procurando por uma solução de uso geral, precisará fazer o seguinte:

  • Importe dados de fuso horário para uma tabela e mantenha essa tabela à medida que as regras de fuso horário mudam. Use essa tabela com um monte de lógica personalizada para resolver o deslocamento para uma data específica.

  • Use xp_regread para obter as chaves de registro do Windows que contêm dados de fuso horário e, novamente, usar um monte de lógica personalizada para resolver o deslocamento para uma data específica. Claro, xp_regread é uma coisa ruim de se fazer, requer certas permissões concedidas e não é suportado ou documentado.

  • Escreva uma função SQLCLR que use o TimeZoneInfo classe em .Net. Infelizmente, este requer um assembly SQLCLR "inseguro" , e pode fazer com que coisas ruins aconteçam.

IMHO, nenhuma dessas abordagens é muito boa e não há uma boa solução para fazer isso diretamente no SQL. A melhor solução seria retornar o valor UTC (o inteiro original ou o datetime em UTC) para o código do aplicativo de chamada e faça a conversão de fuso horário lá (com, por exemplo, TimeZoneInfo em .Net ou mecanismos semelhantes em outras plataformas).

NO ENTANTO - você teve sorte porque o Kuwait está (e sempre esteve) em uma zona que não muda para o horário de verão. Sempre foi UTC+03:00. Então você pode simplesmente adicionar três horas e retornar o resultado:
SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))

Mas reconheça que esta não é uma solução de propósito geral que funcionará em qualquer fuso horário.

Se desejar, você pode retornar um dos outros tipos de dados SQL, como datetimeoffset , mas isso só o ajudará a refletir que o valor é três horas de deslocamento para quem quer que o veja. Isso não tornará o processo de conversão diferente ou melhor.

Resposta atualizada

Criei um projeto para dar suporte a fusos horários no SQL Server. Você pode instalá-lo aqui . Então você pode simplesmente converter assim:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')

Você pode usar qualquer fuso horário do banco de dados IANA tz , incluindo aqueles que usam o horário de verão.

Você ainda pode usar o método que mostrei acima para converter de um timestamp unix. Juntando os dois:
SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')

Atualizado novamente

Com o SQL Server 2016, agora há suporte interno para fusos horários com o AT TIME ZONE declaração. Isso também está disponível no Banco de Dados SQL do Azure (v12).
SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'

Mais exemplos neste anúncio.