时区(Transact-SQL)

适用于:sql Server 2016 (13.x) 及更高版本 Azure SQL 数据库Azure SQL 托管实例Azure Synapse AnalyticsSQL 分析终结点Microsoft FabricWarehouse 中的Microsoft Fabric SQL 数据库在 Microsoft Fabric 中的 fabric SQL 数据库

AT TIME ZONE Transact-SQL(T-SQL)语句将input_date转换为目标时区对应的日期时间偏移值。 当 input_date 没有偏移信息时,函数会应用该时区的偏移,假设 input_date 位于目标时区内。

如果 input_date 作为 日期时间偏移 值提供,则 AT TIME ZONE 子句会利用时区转换规则将其转换为目标时区。

该AT TIME ZONE实现依赖于 Windows 机制,将 datetime 值跨时区转换。

Transact-SQL 语法约定

Syntax

input_date AT TIME ZONE time_zone_value
input_date AT TIME ZONE { 'time_zone_value' | 'LOCAL' }

Arguments

input_date

一个表达式,可解析为 smalldatetime、datetime、datetime2 或 datetimeoffset 值。

“time_zone_value”

目标时区的名称。 time_zone_value是nvarchar(128)。

SQL Server 依赖存储在 Windows 注册表中的时区。 计算机上安装的时区存储于以下注册表配置单元中:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones。

通过 sys.time_zone_info 系统视图还会显示已安装的时区列表。

有关 Linux 上的 SQL Server 时区的详细信息,请参阅 在 Linux 上配置 SQL Server 2022 及更高版本的时区。

{ 'time_zone_value' |'本地' }

目标时区的名称。 time_zone_value 是 nvarchar(128),默认为 LOCAL。

通过 sys.time_zone_info 系统视图,会显示已安装的时区列表。

如果 LOCAL 指定了,则会话当前默认时区值将设置为会话的原始时区值,这可以是数据库范围选项或实例默认值。

返回类型

返回 datetimeoffset 的数据类型。

返回值

目标时区中的 datetimeoffset 值。

Remarks

AT TIME ZONE 应用特定规则来转换 smalldatetime、datetime 和 datetime2 数据类型中的输入值,这些值位于受 DST 更改影响的区间:

  • 如果将时钟向前拨,将当地时间出现与时钟调整持续时间相等的时差。 此持续时间通常为 1 小时,但它也可以是 30 或 45 分钟,具体取决于所在的时区。 落入该时差范围的时间点会按 DST 更改后的偏移量进行转换。

    /*
      Moving to DST in "Central European Standard Time" zone:
      offset changes from +01:00 -> +02:00
      Change occurred on March 27th, 2022 at 02:00:00.
      Adjusted local time became 2022-03-27 03:00:00.
    */
    
    --Time before DST change has standard time offset (+01:00)
    SELECT CONVERT (DATETIME2 (0), '2022-03-27T01:01:00', 126)
        AT TIME ZONE 'Central European Standard Time';
    
    --Result: 2022-03-27 01:01:00 +01:00
    /*
      Adjusted time from the "gap interval" (between 02:00 and 03:00)
      is moved 1 hour ahead and presented with the summer time offset
      (after the DST change)
    */
    SELECT CONVERT (DATETIME2 (0), '2022-03-27T02:01:00', 126)
        AT TIME ZONE 'Central European Standard Time';
    
    --Result: 2022-03-27 03:01:00 +02:00
    
    --Time after 03:00 is presented with the summer time offset (+02:00)
    SELECT CONVERT (DATETIME2 (0), '2022-03-27T03:01:00', 126)
        AT TIME ZONE 'Central European Standard Time';
    
    --Result: 2022-03-27 03:01:00 +02:00
    
  • 如果将时钟向后拨,则 2 个小时的本地时间将有 1 个小时的重叠。 在这种情况下,落入重叠范围的时间点会使用时钟更改之前的偏移量来调整:

    /*
        Moving back from DST to standard time in
        "Central European Standard Time" zone:
        offset changes from +02:00 -> +01:00.
        Change occurred on October 30th, 2022 at 03:00:00.
        Adjusted local time became 2022-10-30 02:00:00
    */
    
    --Time before the change has DST offset (+02:00)
    SELECT CONVERT (DATETIME2 (0), '2022-10-30T01:01:00', 126)
        AT TIME ZONE 'Central European Standard Time';
    
    --Result: 2022-10-30 01:01:00 +02:00
    /*
      Time from the "overlapped interval" is presented with DST offset (before the change)
    */
    SELECT CONVERT (DATETIME2 (0), '2022-10-30T02:00:00', 126)
        AT TIME ZONE 'Central European Standard Time';
    
    --Result: 2022-10-30 02:00:00 +02:00
    
    --Time after 03:00 is regularly presented with the standard time offset (+01:00)
    SELECT CONVERT (DATETIME2 (0), '2022-10-30T03:01:00', 126)
        AT TIME ZONE 'Central European Standard Time';
    
    --Result: 2022-10-30 03:01:00 +01:00
    

由于某些信息(例如时区规则)是在 SQL Server 之外维护的,并且偶尔会发生变化,因此 AT TIME ZONE 函数被归类为非确定性函数。

虽然 Microsoft Fabric 中的数据仓库不支持 datetimeoffset,AT TIME ZONE但仍可与 datetime2 一起使用,如以下示例所示。

Examples

A. 将目标时区偏移量添加到 datetime 而不提供偏移信息

当已知同一时区中已提供原始 datetime 值时,使用 AT TIME ZONE 基于时区规则添加偏移量:

USE AdventureWorks2025;
GO

SELECT SalesOrderID,
       OrderDate,
       OrderDate AT TIME ZONE 'Pacific Standard Time' AS OrderDate_TimeZonePST
FROM Sales.SalesOrderHeader;

结果集如下。

SalesOrderID OrderDate               OrderDate_TimeZonePST
------------ ----------------------- -------------------------------
43659        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00
43660        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00
43661        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00
43662        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00
43663        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00
43664        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00
...

B. 在不同时区之间转换值

以下示例在不同时区之间转换值。 这些 OrderDate 值是 日期时间 ,不随偏移量存储,但已知为太平洋标准时间。 第一步是分配已知偏移,然后转换为新时区:

USE AdventureWorks2025;
GO

SELECT SalesOrderID,
       OrderDate,
       --Assign the known offset only
       OrderDate AT TIME ZONE 'Pacific Standard Time' AS OrderDate_TimeZonePST,
       --Assign the known offset, then convert to another time zone
       OrderDate AT TIME ZONE 'Pacific Standard Time' AT TIME ZONE 'Central European Standard Time' AS OrderDate_TimeZoneCET
FROM Sales.SalesOrderHeader;

结果集如下。

SalesOrderID OrderDate               OrderDate_TimeZonePST          OrderDate_TimeZoneCET
------------ ----------------------- ------------------------------ -------------------------------
43659        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43660        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43661        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43662        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43663        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43664        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
...

还可以在包含时区的局部变量中替换:

USE AdventureWorks2025;
GO

DECLARE @CustomerTimeZone AS NVARCHAR (128) = 'Central European Standard Time';

SELECT SalesOrderID,
       OrderDate,
       --Assign the known offset only
       OrderDate AT TIME ZONE 'Pacific Standard Time' AS OrderDate_TimeZonePST,
       --Assign the known offset, then convert to another time zone
       OrderDate AT TIME ZONE 'Pacific Standard Time' AT TIME ZONE @CustomerTimeZone AS OrderDate_TimeZoneCustomer
FROM Sales.SalesOrderHeader;

结果集如下。

SalesOrderID OrderDate               OrderDate_TimeZonePST          OrderDate_TimeZoneCustomer
------------ ----------------------- ------------------------------ -------------------------------
43659        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43660        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43661        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43662        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43663        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
43664        2022-05-30 00:00:00.000 2022-05-30 00:00:00.000 -07:00 2022-05-30 09:00:00.000 +02:00
...

C. 使用特定时区查询时态表

以下示例使用太平洋标准时间从时间 WideWorldImporters 表中选择数据。

USE WideWorldImporters;
GO

DECLARE @ASOF AS DATETIMEOFFSET;
SET @ASOF = DATEADD(MONTH, -1, GETDATE()) AT TIME ZONE 'UTC';

-- Query state of the table a month ago projecting period
-- columns as Pacific Standard Time
SELECT CustomerID,
       CustomerName,
       ValidFrom AT TIME ZONE 'Pacific Standard Time'
FROM Sales.Customers FOR SYSTEM_TIME AS OF @ASOF;

结果集如下。

CustomerID CustomerName                        ValidFrom
---------- ----------------------------------- ----------------------------------
1          Tailspin Toys (Head Office)         2013-01-01 00:00:00.0000000 -08:00
2          Tailspin Toys (Sylvanite, MT)       2013-01-01 00:00:00.0000000 -08:00
3          Tailspin Toys (Peeples Valley, AZ)  2013-01-01 00:00:00.0000000 -08:00
4          Tailspin Toys (Medicine Lodge, KS)  2013-01-01 00:00:00.0000000 -08:00
5          Tailspin Toys (Gasport, NY)         2013-01-01 00:00:00.0000000 -08:00
6          Tailspin Toys (Jessie, ND)          2013-01-01 00:00:00.0000000 -08:00