如何假设 DATETIME 位于我的本地时区,然后转换为 UTC

lzd*_*ydy 2 sql t-sql sql-server

使用 SQL Server 2016,我有一个使用计算机本地时区插入的date_time类型列。DATETIME我需要将此值转换为 UTC。

我尝试使用

CONVERT(NVARCHAR(19), date_time AT TIME ZONE 'UTC', 127) + 'Z' AS Timestamp
Run Code Online (Sandbox Code Playgroud)

但我现在意识到它会自动假定date_time已经是 UTC 时间,因此不会进行转换。我没有使用DATEADD,因为它不考虑夏令时。

有没有办法告诉 SQL Server 日期时间位于计算机的本地时区,然后使用 AT TIME ZONE 将其转换为 UTC?

编辑:这不是重复的,因为批准的答案中的评论(“是的,但它假设输入时间是 UTC,如果您想从本地时间转换为 UTC,这是毫无意义的”)说明了我概述的问题在这个问题中。

Jer*_*ert 5

AT TIME ZONE是等式的二分之一。另一个是获取机器的时区,即使是 2017 年也没有实际功能SERVERPROPERTY- 你需要在注册表中查找。从 SQL Server 2019 开始(和 Azure SQL),有函数CURRENT_TIMEZONE()但是(在看似奇怪的疏忽中) this 的返回值不能用作子句的输入AT TIME ZONE或与 相关sys.time_zone_info,因此不清楚它的用途是什么服务。

DECLARE @TimeZone NVARCHAR(4000);
EXEC master.dbo.xp_regread 
    'HKEY_LOCAL_MACHINE', 
    'SYSTEM\CurrentControlSet\Control\TimeZoneInformation', 
    'TimeZoneKeyName', 
    @TimeZone OUT;

-- For me, that's 'W. Europe Standard Time'

SELECT {ts '2019-03-31 02:00:00' } AT TIME ZONE @TimeZone AT TIME ZONE 'UTC'
-- Yields '2019-03-31 01:00:00.000 +00:00', DST was not in effect

SELECT {ts '2019-03-31 03:00:00' } AT TIME ZONE @TimeZone AT TIME ZONE 'UTC'
-- *Also* yields '2019-03-31 01:00:00.000 +00:00', DST was in effect
Run Code Online (Sandbox Code Playgroud)

这些示例说明了必须转换未使用实际偏移记录的时间戳的危险:在 DST 周转的“暮光区”中,您得到的时间本质上是不明确的。这种调整的结果只是大部分是正确的,每年两次跳过和重复一个小时。有些数据集可以忍受,有些则不能。