Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Converti una data in un altro fuso orario in SQL Server

Il AT TIME ZONE La clausola è stata introdotta in SQL Server 2016 per convertire una data in un datetimeoffset valore in un fuso orario target.

Questa funzione è simile ad altre funzioni T-SQL, come SWITCHOFFSET() e TODATETIMEOFFSET() , invece, il AT TIME ZONE La clausola consente/(richiede) di specificare la differenza di fuso orario in base al nome, invece di un valore di offset effettivo.

Questo articolo esplora come AT TIME ZONE funziona e ne spiega i vantaggi rispetto alle altre funzioni citate.

Esempio di utilizzo

Ecco un esempio di base di come il AT TIME ZONE la clausola funziona.

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];

Risultato (usando l'output verticale):

Original | 2020-04-01 00:00:00.0000000 +00:00
NZ Time  | 2020-04-01 13:00:00.0000000 +13:00

Ti starai chiedendo perché Microsoft abbia introdotto questa funzionalità quando avresti potuto utilizzare SWITCHOFFSET() funzione per fare la stessa cosa?

Bene, non puoi in realtà fai esattamente la stessa cosa con SWITCHOFFSET() .

Con SWITCHOFFSET() , è necessario fornire l'effettivo spostamento del fuso orario nel formato [+|-]TZH:TZM o come numero intero con segno (per minuti). Ciò significa che devi conoscere l'esatto fuso orario, e indipendentemente dal fatto che quel fuso orario stia attualmente osservando l'ora legale.

Con il AT TIME ZONE clausola, non è necessario che tu lo sappia. Tutto quello che devi sapere è il nome del fuso orario (ed ecco come ottenere il nome del fuso orario).

Esempio di ora legale

Ecco un esempio che dimostra i vantaggi dell'utilizzo di AT TIME ZONE per quanto riguarda l'ora legale.

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];

Risultato (usando l'output verticale):

@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

In Nuova Zelanda, l'ora legale termina il 5 marzo 2020. Pertanto in questo esempio utilizzo due date (1 marzo e 7 marzo).

Quando li converto in "Ora solare della Nuova Zelanda", AT TIME ZONE include automaticamente l'ora legale nel suo calcolo e restituisce la data/ora applicabile.

Quindi possiamo vedere che la data del 1 marzo utilizza un fuso orario di +13:00 e la data del 7 marzo utilizza +12:00 (perché l'ora legale è terminata il 5 marzo).

Se avessi usato SWITCHOFFSET() Avrei dovuto sapere quale differenza di fuso orario utilizzare per ciascuna 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];

Risultato (usando l'output verticale):

@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

Conversione da date senza fuso orario

Puoi anche usare AT TIME ZONE in date senza fuso orario. In effetti, la funzione accetta qualsiasi espressione che può essere risolta in un smalldatetime , data e ora , dataora2 o datetimeoffset valore.

Tuttavia, quando lo fai, devi essere consapevole di come viene calcolato il risultato. Quando la data viene fornita senza informazioni sull'offset, la funzione applica l'offset del fuso orario presupponendo che la data di input sia nel fuso orario di destinazione.

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];

Risultato:

@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

Si noti che sebbene gli scostamenti del fuso orario siano stati applicati come specificato, ciò non ha influito sulla data/ora. Entrambe le date e gli orari risultanti hanno lo stesso valore:è cambiato solo l'offset del fuso orario.

Se questo non è ciò che desideri, puoi aggiungere AT TIME ZONE 'UTC' al mix per convertire prima le date originali in UTC, prima che vengano convertite nel fuso orario desiderato.

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];

Risultato:

@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