我在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
答案 0 :(得分:1)
小心点。 DST是一种非技术性但政治性的政策,可能会随着时间的推移而变化(各国一直在改变DST调整),这需要一个最新的时区数据库。
SQL Server本身并不关心时区:它本身不执行任何时区转换,只执行UTF偏移转换(当已知瞬时本地到UTC转换时使用datetimeoffset
)。它无法告诉您有关区域位置或未来偏移的任何信息,因为这些可以说是属于持久层(即SQL Server)域之外的业务规则。在数据库中存储值时,始终使用UTC datetime
或datetimeoffset
值。当区域信息与用户无关时使用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点。