如何假设DATETIME在我的当地时区,然后转换为UTC

时间:2019-04-25 13:04:29

标签: sql sql-server tsql

使用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则毫无意义”)指出了问题我已经概述了这个问题。

2 个答案:

答案 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 |
+-------------------------+