use*_*567 44 sql-server-2008 sql-server timezone
我的本地开发服务器在中东,但我的生产服务器在英国。
我需要在他们的时区向用户显示日期。例如,如果用户在沙特阿拉伯,那么我需要根据沙特阿拉伯格式显示时间。
我应该创建一个名为 TimeZone 的新数据库表并以 UTC 格式保存时间吗?
Jon*_*gel 56
不幸的是,对此没有快速解决方案。应用程序的国际化应该是最初设计讨论的一部分,因为它确实涉及许多不同领域的核心,包括日期/时间比较和输出格式。
无论如何,要走上正确的道路,必须将时区信息与 time一起存储。换句话说,认识到的日期/时间20130407 14:50是无意义的,而不是(a)包括时区当时的UTC偏差(注释1) ,或(b)保证所有逻辑插入这些值首先转换到一定的固定的偏移(最有可能是 0)。如果没有这些东西,两个给定的时间值是不可比较的,数据就会损坏。(顺便说一下,后一种方法是玩火(注 2);不要那样做。)
在 SQL Server 2008+ 中,您可以使用datetimeoffset数据类型直接存储带有时间的偏移量。(为了完整起见,在 2005 年及之前,我将添加第二列来存储当时的 UTC 偏移值(以分钟为单位)。)
这使得桌面类型的应用程序变得容易,因为这些平台通常具有自动将日期/时间+时区转换为本地时间然后格式化输出的机制,所有这些都基于用户的区域设置。
对于本质上是断开连接的架构的 Web 而言,即使正确设置了后端数据,它也更加复杂,因为您需要有关客户端的信息才能进行转换和/或格式化。这通常是通过用户首选项设置(应用程序在输出之前转换/格式化内容)来完成的,或者只是为每个人显示具有相同固定格式和时区偏移量的内容(这是 Stack Exchange 平台当前所做的)。
您可以看到如果后端数据设置不正确,它会很快变得复杂和笨拙。我不建议沿着这些路径走下去,因为你最终会遇到更多问题。
注 1:
时区的 UTC 偏移量不是固定的:考虑夏令时,其中区域的 UTC 偏移量正负一小时变化。此外,区域的夏令时日期也会定期变化。因此使用datetimeoffset(或组合local time和UTC offset at that time)会导致最大的信息恢复。
笔记2:
这是关于控制数据输入。虽然没有万无一失的方法来验证传入的值,但最好执行一个不涉及计算的简单标准。如果公共 API 需要包含偏移量的数据类型,则调用者将清楚该要求。
如果不是这种情况,调用者必须依赖文档(如果他们阅读了它),或者计算不正确,等等。需要偏移时的故障/错误模式较少,特别是对于分布式系统(甚至只是单独服务器上的网络/数据库,就像这里的情况一样)。
无论如何存储偏移量会用一颗石头杀死两只鸟;即使现在不需要这样做,它也会在以后在必要时提供这种可能性。确实它会占用更多存储空间,但我认为值得进行权衡,因为如果从一开始就没有记录数据,数据就会丢失。
Mat*_*int 16
我已经为 SQL Server 中的时区转换开发了一个全面的解决方案。请参阅GitHub 上的 SQL Server 时区支持。
它正确处理时区之间的转换,以及与 UTC 之间的转换,包括夏令时。
它在概念上类似于 adss 回答中描述的“T-SQL 工具箱”解决方案,但它使用更常见的 IANA/Olson/TZDB 时区而不是 Microsoft 的时区,并且它包括用于保持数据作为新版本维护的实用程序TZDB出来了。
示例用法(回答 OP):
SELECT Tzdb.UtcToLocal(sysutcdatetime(), 'Asia/Riyadh') as CurrentTimeInSaudiArabia
Run Code Online (Sandbox Code Playgroud)
有关其他 API 和详细说明,请参阅GitHub 上的自述文件。
另请注意,由于这是基于 UDF 的解决方案,因此它的设计并非以性能为主要目标。如果此功能内置于 SQL Server 中会更好,类似于该CONVERT_TZ功能在 Oracle 和 MySQL 中的存在方式。
SQL Server 在 2005 年以后进行了修改,其中内部时区以 UTC 格式保存。这主要是由于涉及日志传送的异地复制和 HA 投影仪,并且将日志传送时间保存在不同的时区使得旧方法无法恢复它们。
因此,以 UTC 时间在内部保存所有内容使 SQL Server 能够在全球范围内正常运行。这就是为什么在 Windows 中处理夏令时有点麻烦的原因之一,因为 Outlook 等其他 MS 产品也在内部将日期/时间保存为 UTC,并创建需要修补的偏移量。
我在一家拥有数千台服务器(虽然不是 MS SQL 服务器,而是各种服务器)分布在世界各地的公司工作,如果我们不特别强制一切都按照 UTC 进行,我们都会发疯很快。
我已经在 codeplex 上开发并发布了“T-SQL Toolbox”项目,以帮助任何在 SQL Server 中处理日期时间和时区的人。它是开源的,完全免费使用。
它使用简单的 T-SQL 和开箱即用的附加配置表提供简单的日期时间转换 UDF。
在您的示例中,您可以使用以下示例:
SELECT [DateTimeUtil].[UDF_ConvertLocalToLocalByTimezoneIdentifier] (
'GMT Standard Time', -- the original timezone in which your datetime is stored
'Middle East Standard Time', -- the target timezone for your user
'2014-03-30 01:55:00' -- the original datetime you want to convert
)
Run Code Online (Sandbox Code Playgroud)
这将为您的用户返回转换后的日期时间值。
在 T-SQL Toolbox 数据库中也提供的表“DateTimeUtil.Timezone”中可以找到所有支持的时区的列表。
| 归档时间: |
|
| 查看次数: |
252479 次 |
| 最近记录: |