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

Converter uma data para outro fuso horário no SQL Server


O AT TIME ZONE cláusula foi introduzida no SQL Server 2016 para converter uma data em um datetimeoffset valor em um fuso horário de destino.

Esta função é semelhante a algumas outras funções T-SQL, como SWITCHOFFSET() e TODATETIMEOFFSET() , no entanto, o AT TIME ZONE A cláusula permite/(requer) que você especifique o deslocamento de fuso horário por nome, em vez de um valor de deslocamento real.

Este artigo explora como AT TIME ZONE funciona, e explica seus benefícios em relação às outras funções mencionadas.

Exemplo de uso


Aqui está um exemplo básico de como o AT TIME ZONE cláusula funciona.
DECLARE @dto datetimeoffset = '2020-04-01 00:00:00.0000000 +00:00';
SELECT
  @dto AS [Original],
  @dto AT TIME ZONE 'New Zealand Standard Time' AS [NZ Time];

Resultado (usando saída vertical):
Original | 2020-04-01 00:00:00.0000000 +00:00
NZ Time  | 2020-04-01 13:00:00.0000000 +13:00

Você pode estar se perguntando por que a Microsoft introduziu esse recurso quando você poderia ter usado o SWITCHOFFSET() função para fazer a mesma coisa?

Bem, você não pode na verdade, faça exatamente a mesma coisa com SWITCHOFFSET() .

Com SWITCHOFFSET() , você deve fornecer o deslocamento de fuso horário real no formato [+|-]TZH:TZM ou como um inteiro com sinal (para minutos). Isso significa que você precisa saber o deslocamento exato do fuso horário, e se esse fuso horário está ou não observando o horário de verão.

Com o AT TIME ZONE cláusula, você não precisa saber disso. Tudo o que você precisa saber é o nome do fuso horário (e veja como obter o nome do fuso horário).

Exemplo de horário de verão


Aqui está um exemplo que demonstra o benefício de usar AT TIME ZONE no que diz respeito ao horário de verão.
DECLARE @dto1 datetimeoffset, @dto2 datetimeoffset;
SET @dto1 = '2020-04-01 00:00:00.0000000 +00:00';
SET @dto2 = '2020-04-07 00:00:00.0000000 +00:00';
SELECT
  @dto1 AS [@dto1],
  @dto2 AS [@dto2],
  @dto1 AT TIME ZONE 'New Zealand Standard Time' AS [NZ Time: @dto1],
  @dto2 AT TIME ZONE 'New Zealand Standard Time' AS [NZ Time: @dto2];

Resultado (usando saída vertical):
@dto1          | 2020-04-01 00:00:00.0000000 +00:00
@dto2          | 2020-04-07 00:00:00.0000000 +00:00
NZ Time: @dto1 | 2020-04-01 13:00:00.0000000 +13:00
NZ Time: @dto2 | 2020-04-07 12:00:00.0000000 +12:00

Na Nova Zelândia, o horário de verão termina em 5 de março de 2020. Portanto, neste exemplo, uso duas datas (1 de março e 7 de março).

Quando eu os converto para 'Horário padrão da Nova Zelândia', AT TIME ZONE inclui automaticamente o horário de verão em seu cálculo e retorna a data/hora aplicável.

Assim, podemos ver que a data de 1º de março usa um deslocamento de fuso horário de +13:00 e a data de 7 de março usa +12:00 (porque o horário de verão terminou em 5 de março).

Se eu tivesse usado SWITCHOFFSET() Eu teria que saber qual deslocamento de fuso horário usar para cada data.
DECLARE @dto1 datetimeoffset, @dto2 datetimeoffset;
SET @dto1 = '2020-04-01 00:00:00.0000000 +00:00';
SET @dto2 = '2020-04-07 00:00:00.0000000 +00:00';
SELECT
  @dto1 AS [@dto1],
  @dto2 AS [@dto2],
  SWITCHOFFSET(@dto1, '+12:00') AS [+12:00],
  SWITCHOFFSET(@dto2, '+13:00') AS [+13:00];

Resultado (usando saída vertical):
@dto1  | 2020-04-01 00:00:00.0000000 +00:00
@dto2  | 2020-04-07 00:00:00.0000000 +00:00
+12:00 | 2020-04-01 12:00:00.0000000 +12:00
+13:00 | 2020-04-07 13:00:00.0000000 +13:00

Conversão de datas sem deslocamento de fuso horário


Você também pode usar AT TIME ZONE em datas sem deslocamento de fuso horário. Na verdade, a função aceita qualquer expressão que possa ser resolvida para um smalldatetime , datahora , datahora2 , ou deslocamento de data e hora valor.

No entanto, ao fazer isso, você precisa estar atento a como o resultado é calculado. Quando a data é fornecida sem informações de deslocamento, a função aplica o deslocamento do fuso horário assumindo que a data de entrada está no fuso horário de destino.
DECLARE @dt1 smalldatetime, @dt2 smalldatetime;
SET @dt1 = '2020-04-01 00:00:00';
SET @dt2 = '2020-04-07 00:00:00';
SELECT
  @dt1 AS [@dt1],
  @dt2 AS [@dt2],
  @dt1 AT TIME ZONE 'New Zealand Standard Time' AS [NZ Time: @dt1],
  @dt2 AT TIME ZONE 'New Zealand Standard Time' AS [NZ Time: @dt2];

Resultado:
@dt1          | 2020-04-01 00:00:00
@dt2          | 2020-04-07 00:00:00
NZ Time: @dt1 | 2020-04-01 00:00:00.0000000 +13:00
NZ Time: @dt2 | 2020-04-07 00:00:00.0000000 +12:00

Observe que, embora os deslocamentos de fuso horário tenham sido aplicados conforme especificado, isso não afetou a data/hora. Ambas as datas/horas resultantes têm o mesmo valor – apenas o deslocamento do fuso horário foi alterado.

Se isso não é o que você deseja, você pode adicionar AT TIME ZONE 'UTC' ao mix para primeiro converter as datas originais para UTC, antes de serem convertidas para o fuso horário desejado.
DECLARE @dt1 smalldatetime, @dt2 smalldatetime;
SET @dt1 = '2020-04-01 00:00:00';
SET @dt2 = '2020-04-07 00:00:00';
SELECT
  @dt1 AS [@dt1],
  @dt2 AS [@dt2],
  @dt1 AT TIME ZONE 'UTC' AT TIME ZONE 'New Zealand Standard Time' AS [NZ Time: @dt1],
  @dt2 AT TIME ZONE 'UTC' AT TIME ZONE 'New Zealand Standard Time' AS [NZ Time: @dt2];

Resultado:
@dt1          | 2020-04-01 00:00:00
@dt2          | 2020-04-07 00:00:00
NZ Time: @dt1 | 2020-04-01 13:00:00.0000000 +13:00
NZ Time: @dt2 | 2020-04-07 12:00:00.0000000 +12:00