【问题标题】:How to get timezone offset for historic daylight saving time local date?如何获取历史夏令时本地日期的时区偏移量?
【发布时间】:2022-01-10 11:51:59
【问题描述】:

有一个 SQL Server 在 UTC+1 中使用GETDATE(),所以很容易出现不同的当地时间。夏季为+02:00 (CEST),冬季为+01:00 (CET)。

获取当前时间的时区偏移很容易。 如何获取历史日期的 UTC 偏移量?

日期实际上不言自明——如果分别在 3 月和 10 月最后一个星期日的世界标准时间 1 点之间,则为 DST,否则不是。但这对于每个查询来说都是一种繁琐的启发式方法。

我似乎无法使用SYSDATETIMEOFFSET()/TODATETIMEOFFSET/SWITCHOFFSET/DATENAME(TZOFFSET,…),因为我需要已经知道偏移量。在这种情况下,AT TIME ZONE/sys.time_zone_info 退出了,因为它是 2014 年的旧 SQL 服务器。

这是一个标准问题。除了使用 UTC 日期或存储每个日期的偏移量之外,是否有一种合理的方法可以从特定(地理)时区中的任何日期获取 DST 偏移量?

【问题讨论】:

  • 除非你存储了当时的偏移量,否则你不能隐式地这样做; SQL Server 不知道该值是否尊重日期灯节省。您需要创建某种日历表来表示每年的偏移量,以便您可以显式转换它。而且,当然,当时钟倒退时,您不会知道某个值是否在“重复”小时内。
  • 每年的偏移量都是一样的——它们只是依赖于一个奇怪的规则。当我看到一个没有偏移的 UTC+1 日期时,我马上就知道它的月份。
  • 日期每年都在变化,@dakab。是的,他们在同一周,但实际日期每年都在变化。
  • 不管怎样,如果你使用 MySQL 和 load the zoneinfo data 进入它,你可以做类似 CONVERT_TZ('1995-03-15 14:30', 'UTC', 'Europe/Paris') 的事情来获得历史上正确的时间和位置的时区转换。 zoneinfo database 包含有关白天时间历史变化的信息。由于某种原因,昂贵的 DBMS(Oracle、SQL Server)没有实现这一点。
  • 请记住,例如 10 月转换日 01:30 的时间戳可能是旧时间或新时间。如果不存储偏移量,根本无法知道这一点

标签: sql-server-2014 dst timezone-offset localtime


【解决方案1】:

我调整了this answer 以找到相关的星期日,并使用 CET/CEST 的硬连线决定来解决此问题:

DECLARE @Date DATETIME2(3) = '2008-09-15 13:38:42.951'
DECLARE @DST_Start DATETIME2(0) = (SELECT DATEADD(HOUR,1,DATEADD(DAY,DATEDIFF(DAY,'19000107',DATEADD(MONTH,DATEDIFF(MONTH,0,CONCAT(YEAR(@Date),'-03-01')),30))/7*7,'19000107')));
DECLARE @DST_End   DATETIME2(0) = (SELECT DATEADD(HOUR,1,DATEADD(DAY,DATEDIFF(DAY,'19000107',DATEADD(MONTH,DATEDIFF(MONTH,0,CONCAT(YEAR(@Date),'-10-01')),30))/7*7,'19000107')));
SELECT CONVERT(VARCHAR(29),TODATETIMEOFFSET(@Date,CASE WHEN @Date BETWEEN @DST_Start AND @DST_End THEN '+02:00' ELSE '+01:00' END),126);
-- ⇒ 2008-09-15T13:38:42.951+02:00

这种特定的有机方法没有考虑到调整期间的模糊性,但无论如何这是一个症结。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    • 2017-04-16
    • 2021-08-28
    • 2013-10-17
    • 1970-01-01
    • 2012-08-14
    • 2016-11-25
    相关资源
    最近更新 更多