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?

Foi útil?

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 : 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top