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

时间:2015-12-07 00:08:41

标签: sql-server date timezone dst

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

  

欧洲夏令时在三个时区中观察,从3月的最后一个星期日的01:00 UTC开始,到每年10月的最后一个星期日的01:00 UTC结束。

如何将其更改为SQL函数?

在维基百科上,我找到了这个:

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

2 个答案:

答案 0 :(得分:1)

小心点。 DST是一种非技术性但政治性的政策,可能会随着时间的推移而变化(各国一直在改变DST调整),这需要一个最新的时区数据库。

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

除此之外,SQL Server不提供任何API或功能来从T-SQL代码访问系统(Windows OS')时区数据库。

您需要从应用程序代码执行此操作。在.NET中,您可以使用使用Windows时区数据库的TimeZoneInfo类来获取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

答案 1 :(得分:0)

根据您要在此处生成的任何函数输入的条件,具体代码将有所不同。

例如,以下内容会生成运行时区中下一个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点。