sql >> Databasteknik >  >> RDS >> Sqlserver

Konvertera ett datum till en annan tidszon i SQL Server

AT TIME ZONE klausul introducerades i SQL Server 2016 för att konvertera ett datum till en datetime offset värde i en måltidszon.

Denna funktion liknar vissa andra T-SQL-funktioner, såsom SWITCHOFFSET() och TODATETIMEOFFSET() , dock AT TIME ZONE klausul tillåter/(kräver) att du kan ange tidszonförskjutningen med namn, istället för ett faktiskt förskjutningsvärde.

Den här artikeln undersöker hur AT TIME ZONE fungerar och förklarar dess fördelar jämfört med de andra funktionerna som nämns.

Exempel på användning

Här är ett grundläggande exempel på hur AT TIME ZONE klausul fungerar.

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

Resultat (med vertikal utdata):

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

Du kanske undrar varför Microsoft ens introducerade den här funktionen när du kunde ha använt SWITCHOFFSET() funktion för att göra samma sak?

Tja, du kan inte gör faktiskt exakt samma sak med SWITCHOFFSET() .

Med SWITCHOFFSET() , måste du ange den faktiska tidszonsförskjutningen antingen i formatet [+|-]TZH:TZM eller som ett heltal med tecken (för minuter). Det betyder att du behöver veta den exakta tidszonförskjutningen, och om den tidszonen för närvarande har sommartid eller inte.

Med AT TIME ZONE klausul, det behöver du inte veta. Allt du behöver veta är namnet på tidszonen (och så här får du tidszonens namn).

Exempel på sommartid

Här är ett exempel som visar fördelen med att använda AT TIME ZONE när det gäller sommartid.

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

Resultat (med vertikal utdata):

@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

I Nya Zeeland upphör sommartid den 5 mars 2020. Därför använder jag i det här exemplet två datum (1 mars och 7 mars).

När jag konverterar dem till "New Zealand Standard Time", AT TIME ZONE inkluderar automatiskt sommartid i sin beräkning och returnerar tillämpligt datum/tid.

Så vi kan se att datumet 1 mars använder en tidszonförskjutning på +13:00 och datumet 7 mars använder +12:00 (eftersom sommartid slutade den 5 mars).

Om jag hade använt SWITCHOFFSET() Jag skulle ha behövt veta vilken tidszonsförskjutning jag skulle använda för varje datum.

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

Resultat (med vertikal utdata):

@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

Konvertera från datum utan tidszonförskjutning

Du kan också använda AT TIME ZONE på datum utan tidszonförskjutning. Faktum är att funktionen accepterar alla uttryck som kan lösas till en smalldatetime , datumtid , datetime2 , eller datumtidsförskjutning värde.

Men när du gör detta måste du vara uppmärksam på hur resultatet beräknas. När datumet tillhandahålls utan förskjutningsinformation, tillämpar funktionen förskjutningen av tidszonen förutsatt att inmatningsdatumet är i måltidszonen.

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

Resultat:

@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

Observera att även om tidszonsförskjutningarna tillämpades som specificerat, påverkade detta inte datumet/tiden. Båda resulterande datum/tider har samma värde – endast tidszonsförskjutningen har ändrats.

Om detta inte är vad du vill kan du lägga till AT TIME ZONE 'UTC' till mixen för att först konvertera de ursprungliga datumen till UTC, innan de konverteras till önskad tidszon.

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

Resultat:

@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

  1. Hur formaterar jag mina oracle-frågor så att kolumnerna inte lindas?

  2. Hur visar jag det fullständiga innehållet i en text- eller varchar(MAX)-kolumn i SQL Server 2008 Management Studio?

  3. Jämför DATETIME och DATE ignorerande tidsdel

  4. Vilket är snabbast? VÄLJ SQL_CALC_FOUND_ROWS FRÅN "tabell", eller VÄLJ ANTAL(*)