用于查找下一个欧洲夏令时日期的 SQL Server

Posted

技术标签:

【中文标题】用于查找下一个欧洲夏令时日期的 SQL Server【英文标题】:SQL Server for finding next European Summer Time date 【发布时间】:2016-03-11 12:27:21 【问题描述】:

我在 SQL Server 中有一个表,我想在其中添加一列,以显示今年欧洲夏令时的确切过渡日期。

欧洲夏令时间跨三个时区,从每年 3 月最后一个星期日 01:00 UTC/WET 开始,到 10 月最后一个星期日 01:00 UTC 结束。

如何将其更改为 SQL 函数?

在***上我能找到这个:

用于计算欧洲夏令时开始的公式是 星期日 (31 - ((((5 × y) ÷ 4) + 4) mod 7)) 三月 01:00 UTChttps://en.wikipedia.org/wiki/Summer_Time_in_Europe

【问题讨论】:

你的表架构是什么?你为什么要关注这些信息?为什么要存储它? 在这张表中,我存储了很多城市的名称。我将展示与 UTC 时间的冬季时差和夏季时差。与 UTC 相比,这个城市是 UTC+2 还是 +3 小时。并且还想显示时间何时会从夏令时变为冬令时,因为我想在内部网站上强调这一点。 —— 不要为此使用您自己的数据库。只需使用系统时区数据库并将其公开给您的用户,这样它将始终保持最新状态。 我认为只要将这个公式从***转换成 sql 语法就可以解决我的问题。 【参考方案1】:

小心。 DST 是一项非技术性的政治政策,并且会随着时间的推移而变化(国家/地区一直在更改 DST 调整),这需要最新的时区数据库。

SQL Server 本身不关心时区:它本身不执行任何时区转换,只执行 UTF-offset 转换(当使用 datetimeoffset 时,当已知本地到 UTC 的瞬时转换时)。它无法告诉您有关区域位置或未来偏移量的任何信息,因为这些可以说是属于持久层域(即 SQL Server)之外的业务规则。在数据库中存储值时,始终使用 UTC datetimedatetimeoffset 值。当区域信息与用户无关时使用 UTC datetime(即不要发明自己的 datetime+int 系统,使用 datetimeoffset)。

因此,SQL Server 不提供用于从 T-SQL 代码访问系统(Windows 操作系统)时区数据库的任何 API 或功能。

您需要从应用程序代码中执行此操作。在 .NET 中,您可以使用 TimeZoneInfo 类,它使用 Windows 的时区数据库来获取 DST 日期:

TimeZoneInfo.AdjustmentRule.DateStart
TimeZoneInfo.AdjustmentRule.DateEnd
TimeZoneInfo.AdjustmentRule.DaylightTransitionStart
TimeZoneInfo.AdjustmentRule.DaylightTransitionEnd

https://msdn.microsoft.com/en-us/library/system.timezoneinfo.adjustmentrule(v=vs.110).aspx

【讨论】:

这基本正确,但是 SQL Server 2016 现在有 AT TIME ZONE - 从 CTP 3.1 开始。 See announcement 和 msdn。不过,它只有助于转化,而不是确定过渡日期。 @MattJohnson 作为一个纯粹主义者,这个新功能冒犯了我 :) 这对于s-s-rS、数据仓库等变得很重要。对于OLTP,我同意最好在应用层做这些事情。【参考方案2】:

根据您要在此处生成的任何函数输入的标准是什么,具体的代码会有所不同。

例如,以下内容会生成运行所在时区中未来 100 年的日期/时间列表。

; WITH C1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) T(N))
, C2(N, RN) AS (SELECT 1, ROW_NUMBER() OVER (ORDER BY NEWID()) FROM C1 a CROSS JOIN C1 b)
, TYears AS (SELECT YEAR(GETDATE()) + RN - 1 [Years] FROM C2)
SELECT DATEADD(hh
        , DATEDIFF(hh, GETUTCDATE(), GETDATE())
        , DATEADD(dd
            , 0 - (1 + DATEDIFF(dd, 0, CONVERT(DATE, CONVERT(NVARCHAR, [Years]) + '-03-31')) % 7) % 7
            , CONVERT(DATETIME, CONVERT(NVARCHAR, [Years]) + '-03-31 01:00:00'))) [StartDateTime]
    , DATEADD(hh
        , DATEDIFF(hh, GETUTCDATE(), GETDATE())
        , DATEADD(dd
            , 0 - (1 + DATEDIFF(dd, 0, CONVERT(DATE, CONVERT(NVARCHAR, [Years]) + '-10-31')) % 7) % 7
            , CONVERT(DATETIME, CONVERT(NVARCHAR, [Years]) + '-10-31 01:00:00'))) [EndDateTime]
FROM TYears

基本前提是找到当年 3 月的最后一个星期日,找到 UTC +/- 值,将其添加到 3 月最后一个星期日的凌晨 1 点。

【讨论】:

以上是关于用于查找下一个欧洲夏令时日期的 SQL Server的主要内容,如果未能解决你的问题,请参考以下文章

第三十五章 SQL函数 CURRENT_DATE

从 SQL 表中查找下一个工作日

如何添加关于夏令时时区的每周时间增量

返回给定日期的 BST/GMT

R - 从一年中获取夏令时开始和结束

在 SQL/数据库级别计算夏令时 (DST)