使用AT TIME ZONE获取指定时区的当前时间

Joh*_*ohn 8 sql-server timezone

我试图在SQL Server 2016和Azure SQL中使用新的AT TIME ZONE语法.我只想把目前在伦敦的时间作为datetime夏令时进行调整.在运行以下所有命令时,伦敦的时间是凌晨3点27分.

第一步是获得一个datetimeoffset,我可以成功地做到如下:

DECLARE @dto datetimeoffset
SET @dto = (SELECT GETUTCDATE() AT TIME ZONE 'GMT Standard Time')
SELECT @dto
Run Code Online (Sandbox Code Playgroud)

这会返回一个我期望的值:

2016-04-04 02:27:54.0200000 +01:00
Run Code Online (Sandbox Code Playgroud)

接下来,我想将其转换为a datetime,这是我的应用程序所期望的.我尝试了三种不同的方法,其中没有一种方法可以提供我正在寻找的结果:

SELECT SWITCHOFFSET(@dto,'+00:00')
-- Returns 2016-04-04 01:27:54.0200000 +00:00

SELECT CONVERT(datetime, @dto)
-- Returns 2016-04-04 02:27:54.020

SELECT CONVERT(datetime2, @dto)
-- Returns 2016-04-04 02:27:54.0200000
Run Code Online (Sandbox Code Playgroud)

我觉得我错过了一些明显的东西 - 是否有一种简单的方法来获取datetimeoffset并返回该偏移处的日期/时间部分?

Mat*_*int 25

代码的第一行包含错误:

SELECT GETUTCDATE() AT TIME ZONE 'GMT Standard Time'
Run Code Online (Sandbox Code Playgroud)

GETUTCDATE()返回a datetime,没有时区偏移信息.因此,如MSDN文档中所述:

如果提供inputdate而没有偏移信息,则该函数应用时区的偏移量,假设在目标时区中提供inputdate值.

因此,即使您检索了UTC时间,您也错误地断言该值是在伦敦时间(对于此日期的夏令时,这是UTC + 1).

处理此问题的最简单方法是将UTC时间作为datetimeoffset开始时间.

SELECT SYSDATETIMEOFFSET() AT TIME ZONE 'GMT Standard Time'
Run Code Online (Sandbox Code Playgroud)

这会调用转换功能AT TIME ZONE,在文档中说明:

如果inputdate作为datetimeoffset值提供,则AT TIME ZONE子句使用时区转换规则将其转换为目标时区.

考虑一下,如果您的数据实际上来自datetime某个地方的某个字段,您可能需要使用该功能的两个部分,如下所示:

SELECT mydatetimefield AT TIME ZONE 'UTC' AT TIME ZONE 'GMT Standard Time'
Run Code Online (Sandbox Code Playgroud)

AT TIME ZONE断言该值的第一个调用是UTC,给datetimeoffset第二个调用,将其转换为伦敦时间.

任何这些的输出都是a datetimeoffset,您可以将其转换为或转换为原始问题中显示的datetimedatetime2完全相同的输出.(不要switchoffset用于此.)

此外,伦敦的Windows时区标识符始终是"GMT Standard Time".它包括格林威治标准时间和英国夏令时,它们之间有适当的过渡.不要尝试将其更改为"GMT Daylight Time"- 该标识符不存在.时区标记wiki中也包含在Windows时区的部分中.

  • 谢谢!我能够使用`SELECT CONVERT(datetime, SYSDATETIMEOFFSET() AT TIME ZONE 'GMT Standard Time')`来实现我想要的。也感谢您的精彩解释。 (2认同)

小智 5

由于我无法在其他任何地方找到这个,我想我会分享。您可以通过将 datepart (tz) 与 AT TIME ZONE 结合使用来获得以分钟为单位的偏移量。

datepart(tz,UTC_Date AT TIME ZONE 'Central Standard Time')

select dateadd(MINUTE,datepart(tz,cast('2018-07-02 17:54:41.537' as datetime) AT Time Zone 'Central Standard Time'),'2018-07-02 17:54:41.537') as CentralTime
Run Code Online (Sandbox Code Playgroud)

返回

CentralTime
2018-07-02 12:54:41.537
Run Code Online (Sandbox Code Playgroud)