使用SQL Server 2016,我有一个date_time
类型的DATETIME
列是使用计算机的本地时区插入的。我需要将此值转换为UTC。
我尝试使用
CONVERT(NVARCHAR(19), date_time AT TIME ZONE 'UTC', 127) + 'Z' AS Timestamp
但是我现在意识到它会自动假定date_time
已经是UTC时间,因此不进行任何转换。我没有使用DATEADD
,因为它不代表DST。
有没有办法告诉SQL Server日期时间在计算机的本地时区,然后使用AT TIME ZONE将其转换为UTC?
编辑:这不是重复的,因为已批准答案中的注释(“是,但假定输入时间为UTC,如果要从本地时间转换为UTC则毫无意义”)指出了问题我已经概述了这个问题。
答案 0 :(得分:4)
AT TIME ZONE
是等式的一半。另一个是获取机器的时区,即使是2017年也没有实际功能或SERVERPROPERTY
的时区-您需要在注册表中进行浏览。
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
这些示例说明了必须转换未记录有实际偏移量的时间戳的危险:在DST周转的“暮光区”中,您获得的时间本来就模棱两可。这种调整的结果大部分只是正确的,每年跳过并复制一个小时两次。有些数据集可以接受,有些则不能。
答案 1 :(得分:1)
您只需要告诉查询初始日期位于哪个时区,在初始值后使用AT TIME ZONE
子句,然后在第二个AT TIME ZONE
中将其转换为该时区即可。之后的子句。
默认返回值为DATETIMEOFFSET
,因此如果要删除偏移量,则必须CAST/CONVERT
。我在美国中央时区,所以我用了。您必须为服务器替换正确的时区。
DECLARE @date_time DATETIME = GETDATE();
SELECT
@date_time AT TIME ZONE 'Central Standard Time' AT TIME ZONE 'UTC' AS utc_time_as_datetimeoffset;
SELECT
CAST(@date_time AT TIME ZONE 'Central Standard Time' AT TIME ZONE 'UTC' AS DATETIME) AS utc_time_as_datetime;
结果:
+--------------------------------+
| utc_time_as_datetimeoffset |
+--------------------------------+
| 2019-04-25 13:29:01.057 +00:00 |
+--------------------------------+
+-------------------------+
| utc_time_as_datetime |
+-------------------------+
| 2019-04-25 13:29:01.057 |
+-------------------------+