更新的答案
我已经写了我在原始答案中提到的实用程序,您可以在此处找到。
此外,从SQL Server 2016(和Azure SQL数据库)开始,您现在可以使用
AT TIME ZONE关键字在时区之间进行转换。
原始答案
不幸的是,在SQL Server中没有使用时区的出色解决方案。
我调查了大量你链接的问题,随着这一个也。没有内置的时区功能,
TimeZoneInfo在SQLCLR中的任何使用都需要将该程序集注册为“不安全”。这通常是不希望的。
我还研究了使用SQLCLR中的Noda
Time。您可以在本期中阅读有关它的信息。由于某些项目在内部缓存的方式,还必须将其注册为“不安全”。
最终,无论使用哪种方法,问题都是无法在SQLCLR中缓存任何内容。您不能以线程安全的方式使用静态变量,也不能进行任何线程同步或使用诸如之类的类
ConcurrentDictionary。SQL希望完全控制程序集的线程模型。在“安全”程序集中,仅单线程使用一次扔掉的样式代码可以工作。
希望 最终 将有一个可以在SQLCLR中运行的Noda
Time构建,但是它将是一个不进行任何缓存的特殊构建。因此它的执行速度不会那么快,但可以在确保安全的同时完成工作。
TimeZoneInfo不太可能改变。因此,除非SQL Server团队曾经将时区函数直接正确地带入SQL
Server(如Oracle和Postgres那样),否则您只有几个选择:
不要尝试在数据层中进行时区转换。使用UTC中的
datetime
或datetime2
值,或使用datetimeoffset
带任何偏移量的值。但是,请在应用程序层的时区之间进行所有转换。这是我目前的最佳建议。将时区的所有数据复制到实际的SQL表中,并编写适用于该数据的函数。这不是最好的主意,因为数据经常更改,因此表维护可能是一个挑战。要使功能(包括夏令时更改的所有规则)准确无误,也可能是具有挑战性的。我不知道有哪个项目可以很好地将其捆绑在一起,但是如果有人可以-请在评论中让我知道。
xp_regread
直接从Windows注册表项启用并使用时区数据。更新将为您完成,但是在编写这些功能时您仍然面临相同的挑战。无论如何,启用注册表读取可能与启用不安全的CLR程序集一样具有安全风险。
我正在考虑的另一个想法是编写IANA / Olson TZDB解析器和专门用于SQL
Server的功能。这与上面的选项2相似,但是以可维护的方式完成,并且使用IANA标准数据而不是Windows时区。也许有一天我会去,或者有人会击败我。同样,我目前还不知道有任何项目可以做到这一点,但是如果有人知道一个项目,请在评论中让我知道。(
完成-请参见顶部的更新 )
关于
SWITCHOFFSET-仅在您已经知道目标偏移量的情况下才有效。这是成功的一半,也可能是为什么Microsoft
datetimeoffset在文档中仍将其标记为“不了解夏令时”的原因。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)