【问题标题】:SQL Calculate duration of time in hours crossing DST boundariesSQL 计算跨越 DST 边界的持续时间(以小时为单位)
【发布时间】:2017-06-29 05:53:08
【问题描述】:

在我们的系统中,我们有一个为用户创建班次的存储过程。这些班次具有指定的开始/结束时间和持续时间。当这些转变跨越 DST 边界时,持续时间不正确。举个例子:

declare @start DATETIME = '2017-03-11 22:00:00.000',
@end DATETIME = '2017-03-12 06:00:00.000'
select (DATEDIFF(hh, @start, @end)) as 'Elapsed Hours'

这将返回 8 小时的经过时间。然而,今年 3 月 12 日,夏令时开始,时钟向前移动一个小时。所以这段时间实际经过的小时数只有 7。我知道在 SQL 2016 中我可以使用AT TIME ZONE 函数来解决这个问题,但不幸的是我必须在 SQL 2008 - 2016 中支持它。

我发现另一个问题似乎给了我一个想法: How to create Daylight Savings time Start and End function in SQL Server 我可以使用这些函数来获取 DST 开始/结束日期,然后进行一些计算以查看班次是否跨越这些边界之一,然后应用适当的偏移量,但这对我来说似乎是一个丑陋的选择。首先,并非所有地点都遵守 DST,也不是所有国家都使用相同的 DST 时间表......所以我认为必须有更好的方法来做到这一点。社区中是否有其他人遇到过这个问题并找到了更好的方法来处理它?

【问题讨论】:

  • 您是否保证永远不必确定 11 月的第一个星期日 01:30 的含义(假设上下文是美国)?当您“回退”时,您将有一个小时的重复时间,您无法根据当地时间进行排序。
  • 这是个好问题。我认为我们不必担心现在是哪个 1:30。但我需要对此进行研究,以了解应用程序在该时间段内的行为方式。
  • 好的,我们不需要担心这意味着什么。因为这是轮班/工作时间安排的所有逻辑。在一年中的任何一天 22:00 - 01:30 工作的人,即使在 DST 更改日期也总是只工作 3.5 小时,因为他们的轮班在 DST 02:00 转换之前结束。只有当有人跨越这个界限工作时,它才会发挥作用,因为他们要么必须额外工作一个小时,要么少工作一小时。

标签: sql-server tsql dst


【解决方案1】:

由于您在不同地点的 DST 时间表中发现了不确定性,因此通常建议以 UTC 进行所有日期时间计算,并以本地时间显示给客户。 DST 规则可以根据当地法律随时更改,即使在不同城市之间,UTC 是迄今为止计算时间的最佳方式。

为了更加清晰而进行编辑:即使是 SQL 2016 修复程序也将依赖人工干预和规则更新来保持最新状态,因为不同的国家、州和城市对其 DST 法律进行了更改。 UTC 是您可以使用的最稳定可靠的工具。

【讨论】:

  • 这是我可以同意的。不幸的是,对于我们的软件,我们有一个概念,即所有时间都使用当地时间存储在我们的数据库中......所以将其更改为 UTC 并非易事。
  • @Nathan,这很不幸。在这种情况下,您可以将信息沿着责任树向上移动并使其成为其他人的问题吗?或者至少让他们知道,即使有服务器升级和复杂的功能,非UTC方法也只会“相当不错”。
  • 是的,我真的不能让它成为别人的问题。我有责任在 3 月 DST 开始之前确定我们可以解决的问题。幸运的是,我们的大多数客户都是美国的,我可以为亚利桑那州的客户或其他不遵守 DST 的类似地区的客户添加一个覆盖标志。但看起来我只需要选择“非常好”选项,这将允许我为将来重构为 UTC 方法提出论据。
  • 是的,听起来“相当不错”是您最好的选择。由于它主要位于美国,它可能更接近“足够好”。除此之外,无论如何,我给你们一个 A+,以在 3 月 12 日之前发现一个 3 月 12 日的问题。我们都应该努力做到积极主动。
  • 我很乐意接受这一点,但我们在去年 11 月 DST 结束时发现了这个问题......现在我们正试图在 DST 再次开始之前修复它。
猜你喜欢
  • 1970-01-01
  • 2021-03-13
  • 2014-02-27
  • 2019-01-07
  • 1970-01-01
  • 1970-01-01
  • 2020-03-07
  • 2016-06-03
  • 1970-01-01
相关资源
最近更新 更多