sql >> Base de Datos >  >> RDS >> Sqlserver

Convertir una fecha a otra zona horaria en SQL Server

El AT TIME ZONE La cláusula se introdujo en SQL Server 2016 para convertir una fecha en un datetimeoffset valor en una zona horaria de destino.

Esta función es similar a otras funciones de T-SQL, como SWITCHOFFSET() y TODATETIMEOFFSET() , sin embargo, el AT TIME ZONE La cláusula le permite/(requiere) que especifique la compensación de la zona horaria por nombre, en lugar de un valor de compensación real.

Este artículo explora cómo AT TIME ZONE funciona y explica sus beneficios en comparación con las otras funciones mencionadas.

Ejemplo de uso

Este es un ejemplo básico de cómo AT TIME ZONE funciona la cláusula.

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 salida vertical):

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

Tal vez se pregunte por qué Microsoft incluso introdujo esta función cuando podría haber usado el SWITCHOFFSET() función para hacer lo mismo?

Bueno, no puedes en realidad hacer exactamente lo mismo con SWITCHOFFSET() .

Con SWITCHOFFSET() , debe proporcionar el desplazamiento de la zona horaria real en el formato [+|-]TZH:TZM o como un número entero con signo (para minutos). Esto significa que necesita saber el desplazamiento de la zona horaria exacta, y independientemente de si esa zona horaria está observando actualmente el horario de verano.

Con la AT TIME ZONE cláusula, no necesita saber eso. Todo lo que necesita saber es el nombre de la zona horaria (y aquí le indicamos cómo obtener el nombre de la zona horaria).

Ejemplo de horario de verano

Aquí hay un ejemplo que demuestra el beneficio de usar AT TIME ZONE con respecto al horario de verano.

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 salida 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

En Nueva Zelanda, el horario de verano finaliza el 5 de marzo de 2020. Por lo tanto, en este ejemplo utilizo dos fechas (1 de marzo y 7 de marzo).

Cuando los convierto a la "hora estándar de Nueva Zelanda", AT TIME ZONE incluye automáticamente el horario de verano en su cálculo y devuelve la fecha/hora aplicable.

Así que podemos ver que la fecha del 1 de marzo usa una diferencia de zona horaria de +13:00 y la fecha del 7 de marzo usa +12:00 (porque el horario de verano finalizó el 5 de marzo).

Si hubiera usado SWITCHOFFSET() Tendría que haber sabido qué compensación de zona horaria usar para cada fecha.

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 salida 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

Convertir desde fechas sin desplazamiento de zona horaria

También puedes usar AT TIME ZONE en fechas sin desplazamiento de zona horaria. De hecho, la función acepta cualquier expresión que se pueda resolver en un smalldatetime , fechahora , fechahora2 o datetimeoffset valor.

Sin embargo, cuando haga esto, debe tener en cuenta cómo se calcula el resultado. Cuando la fecha se proporciona sin información de compensación, la función aplica la compensación de la zona horaria suponiendo que la fecha de entrada se encuentra en la zona horaria 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

Tenga en cuenta que aunque las compensaciones de zona horaria se aplicaron según lo especificado, esto no afectó la fecha/hora. Ambas fechas/horas resultantes tienen el mismo valor; solo ha cambiado el desplazamiento de la zona horaria.

Si esto no es lo que desea, puede agregar AT TIME ZONE 'UTC' a la mezcla para convertir primero las fechas originales a UTC, antes de convertirlas a la zona horaria deseada.

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