如何使用 SQL Server 2016+ 中的 AT TIME ZONE 将 UTC 日期时间转换为服务器本地时间
How do I convert a datetime in UTC to the server's local time using AT TIME ZONE in SQL Server 2016+
使用 SQL Server 2016 或更新版本,我想将表示 UTC 值的日期时间转换为服务器上的本地时间。
我想使用 AT TIME ZONE,但它假设您明确知道服务器的时区。我们的产品可能安装在世界各地,所以我无法假设时区。
有没有办法(不使用 CLR 或类似工具)获取服务器时区的名称,以便我可以在 AT TIME ZONE 调用中使用它?
或者在 SQL 2016 年是否有其他方法可以将 UTC 转换为本地服务器?
-- how do set a value for @TZ that has the server's time zone name
DECLARE @TZ NVARCHAR(100) = 'Server Time Zone'
DECLARE @D DATETIMEOFFSET = '2017-01-01T00:00:00+00:00'
SELECT @D AT TIME ZONE @Tz
您可以使用 getdate() 和 getutcdate() 之间的日期差异(以分钟为单位)来确定您与 UTC 的差异并将其应用于新的时间戳。 SQLAuthority 还提供了一种获取服务器时区的好方法。
DECLARE @TimeZone VARCHAR(50)
EXEC MASTER.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
'SYSTEM\CurrentControlSet\Control\TimeZoneInformation',
'TimeZoneKeyName',@TimeZone OUT
SELECT @TimeZone
没有在实际项目应用中尝试过,希望对您有所帮助。
DATENAME(TZOFFSET , SYSDATETIMEOFFSET())
这应该为您提供服务器时间偏移量,然后尝试查询匹配的时区名称以用于 AT TIME ZONE。它可能可以 return 多个匹配的时区名称,但我们只需要一个,只要它具有相同的偏移量即可进行准确转换。
下面的示例脚本:
DECLARE @TimeZoneName NVARCHAR(100);
SELECT TOP 1 @TimeZoneName = name FROM sys.time_zone_info WHERE current_utc_offset = DATENAME(TZOFFSET , SYSDATETIMEOFFSET())
SELECT GETUTCDATE() AT TIME ZONE @TimeZoneName;
似乎在 SQL 2016 年无法不依赖 CLR 或 xp_regread 来执行此操作,因为我想要 SQL 用户拥有最小权限。
最后,决定创建一个 UDF,它将 return 服务器的时区。
创造性的部分是UDF是动态创建的,在UDF创建时间使用xp_regread读取服务器的时区,之后的时间zone 本质上是该 UDF 中的 hard-coded。
我假设如果用户有权创建 UDF,他们可能也有权调用 xp_regread。创建后,不需要特殊权限。
使用 SQL Server 2016 或更新版本,我想将表示 UTC 值的日期时间转换为服务器上的本地时间。
我想使用 AT TIME ZONE,但它假设您明确知道服务器的时区。我们的产品可能安装在世界各地,所以我无法假设时区。
有没有办法(不使用 CLR 或类似工具)获取服务器时区的名称,以便我可以在 AT TIME ZONE 调用中使用它?
或者在 SQL 2016 年是否有其他方法可以将 UTC 转换为本地服务器?
-- how do set a value for @TZ that has the server's time zone name
DECLARE @TZ NVARCHAR(100) = 'Server Time Zone'
DECLARE @D DATETIMEOFFSET = '2017-01-01T00:00:00+00:00'
SELECT @D AT TIME ZONE @Tz
您可以使用 getdate() 和 getutcdate() 之间的日期差异(以分钟为单位)来确定您与 UTC 的差异并将其应用于新的时间戳。 SQLAuthority 还提供了一种获取服务器时区的好方法。
DECLARE @TimeZone VARCHAR(50)
EXEC MASTER.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
'SYSTEM\CurrentControlSet\Control\TimeZoneInformation',
'TimeZoneKeyName',@TimeZone OUT
SELECT @TimeZone
没有在实际项目应用中尝试过,希望对您有所帮助。
DATENAME(TZOFFSET , SYSDATETIMEOFFSET())
这应该为您提供服务器时间偏移量,然后尝试查询匹配的时区名称以用于 AT TIME ZONE。它可能可以 return 多个匹配的时区名称,但我们只需要一个,只要它具有相同的偏移量即可进行准确转换。
下面的示例脚本:
DECLARE @TimeZoneName NVARCHAR(100);
SELECT TOP 1 @TimeZoneName = name FROM sys.time_zone_info WHERE current_utc_offset = DATENAME(TZOFFSET , SYSDATETIMEOFFSET())
SELECT GETUTCDATE() AT TIME ZONE @TimeZoneName;
似乎在 SQL 2016 年无法不依赖 CLR 或 xp_regread 来执行此操作,因为我想要 SQL 用户拥有最小权限。
最后,决定创建一个 UDF,它将 return 服务器的时区。
创造性的部分是UDF是动态创建的,在UDF创建时间使用xp_regread读取服务器的时区,之后的时间zone 本质上是该 UDF 中的 hard-coded。
我假设如果用户有权创建 UDF,他们可能也有权调用 xp_regread。创建后,不需要特殊权限。