DateDiff - 夏令时问题

DateDiff - DST issue

背景

我有一个场景,我正在计算两个日期之间的差异。虽然增量差异很明显,但最终计算引入了 60 分钟(1 小时)的差异。

经过调查和 "hair pulling" 事件后,我确定 11 月的 DST 转换是造成 60 分钟(1 小时)差异的原因。

场景

declare @sdate datetime = '2016-10-29 06:03:00.000PM'
declare @edate datetime = '2016-11-29 11:59:00.000PM'

select 
    DATEDIFF(HOUR, @sdate, @edate),
    DATEDIFF(Minute, @sdate, @edate),
    DATEDIFF(Second, @sdate, @edate)

问题

最终,我需要简单地 return @sdate@edate 变量之间的秒数或分钟数。我知道一年中会有两次,差值将相差 60 分钟(1 小时),加上或减去,我想在我的 sql 声明中说明已知的差异。

如果可能,我如何在基于集合的操作中考虑 DST 调整?

目前,我得到 44996 作为差异,但这是未调整的时差。我要找的是45056,就是调整后的时差

SQL 服务器中的 datetime 类型不知道时区或与 UTC 的偏移量。为了考虑 DST,您需要使用 datetimeoffset 类型。

declare @sdate datetimeoffset = '2016-10-29 06:03:00.000PM -05:00'
declare @edate datetimeoffset = '2016-11-29 11:59:00.000PM -06:00'

select 
    DATEDIFF(Hour, @sdate, @edate),
    DATEDIFF(Minute, @sdate, @edate),
    DATEDIFF(Second, @sdate, @edate)

考虑到开始和结束的偏移量相差一个小时,这将给出您要求的结果。

棘手的部分是如何确定开始的偏移量。如果你是 运行 SQL 2016,或者 Azure SQL DB,那么你可以使用 AT TIME ZONE 函数来确定它。

declare @dt datetime = '2016-10-29 06:03:00.000PM'
declare @dto = @dt AT TIME ZONE 'Central Standard Time'

但是既然你说你是 运行 SQL 2012 年,你将不得不编写自己的函数来了解夏令时在你所在时区的开始和结束时间,或者你可以使用我的SQL Server Time Zone Support 包来做到这一点:

declare @dt datetime = '2016-10-29 06:03:00.000PM'
declare @tz varchar = 'America/Chicago'
declare @dto = Tzdb.SwitchZone(Tzdb.LocalToUtc(@dt, @tz, 1, 1), @tz)

请注意 an open item 可以将其简化为单个函数,但以上内容目前应该可以使用。