Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Convertir une date en un autre fuseau horaire dans SQL Server

Le AT TIME ZONE La clause a été introduite dans SQL Server 2016 pour convertir une date en un datetimeoffset valeur dans un fuseau horaire cible.

Cette fonction est similaire à certaines autres fonctions T-SQL, telles que SWITCHOFFSET() et TODATETIMEOFFSET() , cependant, le AT TIME ZONE La clause vous permet/(exige) de spécifier le décalage de fuseau horaire par son nom, au lieu d'une valeur de décalage réelle.

Cet article explique comment AT TIME ZONE fonctionne et explique ses avantages par rapport aux autres fonctions mentionnées.

Exemple d'utilisation

Voici un exemple de base de la façon dont le AT TIME ZONE la clause fonctionne.

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

Résultat (en utilisant la sortie verticale) :

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

Vous vous demandez peut-être pourquoi Microsoft a même introduit cette fonctionnalité alors que vous auriez pu utiliser le SWITCHOFFSET() fonction pour faire la même chose ?

Eh bien, vous ne pouvez pas faire exactement la même chose avec SWITCHOFFSET() .

Avec SWITCHOFFSET() , vous devez fournir le décalage horaire réel au format [+|-]TZH:TZM ou sous la forme d'un entier signé (pour les minutes). Cela signifie que vous devez connaître le décalage horaire exact, et si oui ou non ce fuseau horaire observe actuellement l'heure d'été.

Avec le AT TIME ZONE clause, vous n'avez pas besoin de le savoir. Tout ce que vous devez savoir est le nom du fuseau horaire (et voici comment obtenir le nom du fuseau horaire).

Exemple d'heure d'été

Voici un exemple qui démontre l'avantage d'utiliser AT TIME ZONE en ce qui concerne l'heure d'été.

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

Résultat (en utilisant la sortie 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

En Nouvelle-Zélande, l'heure d'été se termine le 5 mars 2020. Par conséquent, dans cet exemple, j'utilise deux dates (le 1er mars et le 7 mars).

Lorsque je les convertis en "heure normale de Nouvelle-Zélande", AT TIME ZONE inclut automatiquement l'heure d'été dans son calcul et renvoie la date/heure applicable.

Nous pouvons donc voir que la date du 1er mars utilise un décalage de fuseau horaire de +13:00 et que la date du 7 mars utilise +12:00 (car l'heure d'été s'est terminée le 5 mars).

Si j'avais utilisé SWITCHOFFSET() J'aurais dû savoir quel décalage horaire utiliser pour chaque date.

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

Résultat (en utilisant la sortie 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

Conversion de dates sans décalage de fuseau horaire

Vous pouvez également utiliser AT TIME ZONE à des dates sans décalage horaire. En fait, la fonction accepte toute expression pouvant être résolue en smalldatetime , dateheure , dateheure2 , ou datetimeoffset valeur.

Cependant, lorsque vous faites cela, vous devez être conscient de la façon dont le résultat est calculé. Lorsque la date est fournie sans informations de décalage, la fonction applique le décalage du fuseau horaire en supposant que la date d'entrée se trouve dans le fuseau horaire cible.

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

Résultat :

@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

Notez que bien que les décalages de fuseau horaire aient été appliqués comme spécifié, cela n'a pas affecté la date/l'heure. Les deux dates/heures résultantes ont la même valeur - seul le décalage horaire a changé.

Si ce n'est pas ce que vous voulez, vous pouvez ajouter AT TIME ZONE 'UTC' au mélange afin de convertir d'abord les dates d'origine en UTC, avant qu'elles ne soient converties dans le fuseau horaire souhaité.

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

Résultat :

@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