TSQL: Como converter a hora local para UTC? (SQL Server 2008)
-
05-07-2019 - |
Pergunta
Estamos lidando com um aplicativo que precisa para lidar com dados em tempo globais de diferentes fusos horários e horário configurações de economia de tempo. A idéia é armazenar tudo em formato UTC internamente e só converter e para trás para as interfaces de usuário localizadas. O SQL Server oferece nenhum mecanismos para lidar com as traduções dado um tempo, um país e um fuso horário?
Este deve ser um problema comum, por isso estou surpreso google não aparecer nada utilizável.
Os ponteiros?
Solução
7 anos se passaram e ...
realmente há este novo recurso SQL Server 2016, que faz exatamente o que você precisa.
Ele é chamado AT TIME ZONE e converte a data para um fuso horário especificado considerando DST (horário de verão) muda.
Mais informações aqui:
https://msdn.microsoft.com/en-us/library/mt612795.aspx
Outras dicas
Isso funciona para datas que atualmente têm compensado como anfitrião do SQL Server da mesma UTC; ele não leva em conta o horário de verão. Substitua YOUR_DATE
com a data local para converter.
SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);
Enquanto algumas destas respostas, poderá ir no estádio, você não pode fazer o que você está tentando fazer com datas arbitrárias para SqlServer 2005 e mais cedo por causa do horário de verão. Usando a diferença entre a corrente UTC local e atual vai me dar o deslocamento como existe hoje. Eu não encontrei uma maneira de determinar o que o deslocamento teria sido para a data em questão.
Dito isso, eu sei que SqlServer 2008 oferece novas funções de data que pode resolver essa questão, mas as pessoas que utilizam uma necessidade versão anterior para estar ciente das limitações.
A nossa abordagem é persistir UTC e realizar a conversão no lado do cliente, onde temos mais controle sobre a precisão do conversão.
SQL Server 2008 tem um tipo chamado datetimeoffset
. É muito útil para este tipo de coisas.
http://msdn.microsoft.com/en-us/library /bb630289.aspx
Em seguida, você pode usar a função SWITCHOFFSET
para movê-lo de um fuso horário para outro, mas ainda mantendo o mesmo valor UTC.
http://msdn.microsoft.com/en-us/library /bb677244.aspx
Rob
Você pode usar o meu SQL Server Tempo para converter entre IANA fusos horários padrão, as aqui .
UTC para Local é assim:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')
Local para UTC é assim:
SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)
As opções numéricas são bandeira para controlar o comportamento quando os valores de tempo locais são afetados pelo horário de verão. Estes são descritos em detalhe na documentação do projeto.
Aqui está o código para converter DateTime
uma zona para outra DateTime
zona
DECLARE @UTCDateTime DATETIME = GETUTCDATE();
DECLARE @ConvertedZoneDateTime DATETIME;
-- 'UTC' to 'India Standard Time' DATETIME
SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time'
SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS IndiaStandardTime
-- 'India Standard Time' to 'UTC' DATETIME
SET @UTCDateTime = @ConvertedZoneDateTime AT TIME ZONE 'India Standard Time' AT TIME ZONE 'UTC'
SELECT @ConvertedZoneDateTime AS IndiaStandardTime,@UTCDateTime AS UTCDATE
Nota ??em>: AT TIME ZONE
funciona somente em SQL Server 2016 + e a vantagem é que ele considera automaticamente Daylight ao converter para um determinado fuso horário
Eu tendem a inclinar-se para usar DateTimeOffset para todo o armazenamento de data e hora que não está relacionado a um evento local. (Ie: Reunião / partido, etc, doze horas - três horas no museu)
Para obter o DTO atual como UTC:
DECLARE @utcNow DATETIMEOFFSET = CONVERT(DATETIMEOFFSET, SYSUTCDATETIME())
DECLARE @utcToday DATE = CONVERT(DATE, @utcNow);
DECLARE @utcTomorrow DATE = DATEADD(D, 1, @utcNow);
SELECT @utcToday [today]
,@utcTomorrow [tomorrow]
,@utcNow [utcNow]
NOTA: Eu sempre usará UTC ao enviar sobre o fio ... do lado do cliente JS pode facilmente chegar a / do UTC local. Veja: new Date().toJSON()
...
A JS seguinte irá lidar com a análise de uma data UTC / GMT em formato ISO8601 para uma data e hora local.
if (typeof Date.fromISOString != 'function') {
//method to handle conversion from an ISO-8601 style string to a Date object
// Date.fromISOString("2009-07-03T16:09:45Z")
// Fri Jul 03 2009 09:09:45 GMT-0700
Date.fromISOString = function(input) {
var date = new Date(input); //EcmaScript5 includes ISO-8601 style parsing
if (!isNaN(date)) return date;
//early shorting of invalid input
if (typeof input !== "string" || input.length < 10 || input.length > 40) return null;
var iso8601Format = /^(\d{4})-(\d{2})-(\d{2})((([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d{1,12}))?)?)?)?)?([Zz]|([-+])(\d{2})\:?(\d{2}))?$/;
//normalize input
var input = input.toString().replace(/^\s+/,'').replace(/\s+$/,'');
if (!iso8601Format.test(input))
return null; //invalid format
var d = input.match(iso8601Format);
var offset = 0;
date = new Date(+d[1], +d[2]-1, +d[3], +d[7] || 0, +d[8] || 0, +d[10] || 0, Math.round(+("0." + (d[12] || 0)) * 1000));
//use specified offset
if (d[13] == 'Z') offset = 0-date.getTimezoneOffset();
else if (d[13]) offset = ((parseInt(d[15],10) * 60) + (parseInt(d[16],10)) * ((d[14] == '-') ? 1 : -1)) - date.getTimezoneOffset();
date.setTime(date.getTime() + (offset * 60000));
if (date.getTime() <= new Date(-62135571600000).getTime()) // CLR DateTime.MinValue
return null;
return date;
};
}
Sim, até certo ponto, como detalhado aqui .
A abordagem que eu usei (pré-2008) é para fazer a conversão na lógica de negócios .NET antes de inserir na base de dados.
Você pode usar a função GETUTCDATE () para obter UTC datetime Provavelmente, você pode selecionar diferença entre GETUTCDATE () e GETDATE () e usar essa diferença para ajust suas datas para UTC
Mas eu concordo com a mensagem anterior, que é muito mais fácil de controlar datetime direito na camada de negócios (em .NET, por exemplo).
Exemplo de uso:
SELECT
Getdate=GETDATE()
,SysDateTimeOffset=SYSDATETIMEOFFSET()
,SWITCHOFFSET=SWITCHOFFSET(SYSDATETIMEOFFSET(),0)
,GetutcDate=GETUTCDATE()
GO
Retorna:
Getdate SysDateTimeOffset SWITCHOFFSET GetutcDate
2013-12-06 15:54:55.373 2013-12-06 15:54:55.3765498 -08:00 2013-12-06 23:54:55.3765498 +00:00 2013-12-06 23:54:55.373