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



我正在尝试在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

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

2016-04-04 02:27:54.0200000 +01:00

接下来,我想将其转换为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

我觉得我错过了一些显而易见的东西——有没有一种简单的方法来获取datetimeoffset并只返回偏移处的日期/时间部分?

代码的第一行包含错误:

SELECT GETUTCDATE() AT TIME ZONE 'GMT Standard Time'

GETUTCDATE()返回一个没有时区偏移信息的datetime。如MSDN文档中所述:

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

因此,即使您检索到UTC时间,您也错误地断言该值为伦敦时间(该日期的夏令时为UTC+1)。

处理这一问题的最简单方法是首先获取UTC时间作为datetimeoffset

SELECT SYSDATETIMEOFFSET() AT TIME ZONE 'GMT Standard Time'

这调用了AT TIME ZONE转换功能,该功能在文档中表示:

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

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

SELECT mydatetimefield AT TIME ZONE 'UTC' AT TIME ZONE 'GMT Standard Time'

AT TIME ZONE的第一个调用断言该值以UTC为单位,为第二个调用提供datetimeoffset,后者将其转换为伦敦时间。

其中任何一个的输出都是datetimeoffset,您可以将其强制转换或转换为datetimedatetime2,就像您在原始问题中显示的那样。(不要使用switchoffset。)

此外,伦敦的Windows时区标识符始终为"GMT Standard Time"。它包括格林尼治标准时间和英国夏令时,两者之间有适当的转换。不要尝试将其更改为"GMT Daylight Time"-该标识符不存在。时区标签wiki中关于Windows时区的部分也介绍了这一点。

由于我在其他任何地方都找不到这个,我想我可以分享。您可以通过将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

返回

CentralTime
2018-07-02 12:54:41.537

我建议您只将其存储为字符串,并限定它是本地时间表示,否则,如果服务器时间正确,但不在同一时区,SQL Server内部存储的时间将是错误的实际/物理时间。这就是为什么您不能使用convert来表示相同的值,因为您实际上是在从实际发生的时间更改日期时间值,而不仅仅是重新表示它,即日期时间始终存储为UTC,而是在服务器的时区中输入和显示,所以如果您在日期时间字段中输入本地时间,服务器将该时间解释为服务器时区中的时间,而不是事件的实际时间,如果本地时间与服务器不同,则会导致存储的时间导航/偏差>如果您随后将相同的数据提供给不同时区的其他系统,它们将有不正确的数据,并且可能会变得混乱。将正确的值存储在datetime字段中,并根据需要将其显示为字符串。

相关内容

  • 没有找到相关文章

最新更新