5 sql-server t-sql timezone datetime date
我的计算机/SQL Server 2014 使用比 UTC 时间晚 5 小时的东部时区。但是当我运行以下代码时,我得到了 4 小时的差异。
CREATE TABLE datetimeoffsetfunction(
servertime DATETIME2,
utc_servertime DATETIME2,
offset_datetime DATETIMEOFFSET,
switch_offset DATETIMEOFFSET,
to_datetime DATETIMEOFFSET
);
INSERT INTO datetimeoffsetfunction
VALUES ( SYSDATETIME(),
SYSUTCDATETIME(),
SYSDATETIMEOFFSET(),
SWITCHOFFSET( SYSDATETIMEOFFSET(), '+05:00'),
TODATETIMEOFFSET( SYSDATETIME(), '+05:00')
);
The result I got is
servertime: 2016-07-09 23:59:16.4770556
utc_servertime: 2016-07-10 03:59:16.4770556
offset_datetime: 2016-07-09 23:59:16.4770556 -04:00
switch_offset: 2016-07-10 08:59:16.4770556 +05:00
to_datetime: 2016-07-09 23:59:16.4770556 +05:00
Run Code Online (Sandbox Code Playgroud)
servertime 是我的系统时间,考虑到夏令时,我可以解释为什么 servertime 和 utc_servertime 之间只有四个小时的差异。但我确实希望offset_datetime为 2016-07-09 23:59:16.4770556 -05:00除非 SQL Serve 现在考虑了夏令时。
所以我的问题是现在是否自动考虑夏令时是 SQL Server,至少从 2014 年开始?
现在是否自动考虑夏令时是 SQL Server,至少从 2014 年开始?
不,SQL Server 2014 不是“DST 感知的”,您的测试也没有显示它。
首先,你的第4和第5的测试-SWITCHOFFSET( SYSDATETIMEOFFSET(), '+05:00')并TODATETIMEOFFSET( SYSDATETIME(), '+05:00')分别-都出现了+05:00,因为这正是你告诉他们这样做。
接下来,SYSDATETIMEOFFSET()显示-04:00是因为该偏移量目前是您服务器的时区(它确实发生变化,否则它不会显示大约一年中的一半时间)和 UTC 之间的真正差异,UTC 在这一年中不会发生变化。然而,这确实表明 DST 感知:它是 DST 感知的操作系统,这是服务器的当前时间如何根据 DST 变化的。
具有 DST 感知能力意味着在切换时区时可以考虑之前期间和其他时区的 DST 日期边界。这需要时区知识。但是,SQL Server(至少在 SQL Server 2016 之前)没有 TimeZones 的概念。偏移量就是这样:距 UTC 的特定小时数和分钟数。相比之下,时区是一个规则,它规定了一个特定的偏移量,如果曾经应用夏令时(一些时区不参与 DST),如果应用了 DST,那么这些日期边界是什么(这是一个法律问题,可以改变时间,每个地区)。
因此,具有 DST 感知能力意味着您可以将过去的日期转换为当前时区或任意两个时区之间的任何日期或从中转换,这两个时区都不是服务器的当前时区。意思是,具有 DST 感知能力的 SQL Server 表明您可以从以下内容进行转换:
-04:00无法确定该偏移量何时为-05:00。更多信息和一些例子
如上所述,时区偏移量不是时区:它们只是时区的一个属性。意思是,“美国/东部”(又名“America/New_York”)时区(即 EST / EDT)不会被识别-04:00为-05:00;它是一个区域,有东西向的边界,基本偏移量为-05:00,并参与夏令时,因此有一个偏移量 -- +01:00-- 以及何时应用该 DST 偏移量的特定开始日期和结束日期. 您可以在TimeZoneDB.com上查看信息。
此时区信息的主数据库由 Internet 名称分配机构 (IANA) 维护,可在以下位置找到:
http://www.iana.org/time-zones
时区信息由各个政府决定。一些国家参加 DST,其他国家不参加。不同国家/州内的一些城市选择加入或退出父区域规则。请参阅TimeAndDate.com 上的2016年世界各地的夏令时页面,以获取世界各地各种开始和结束日期的图表(至少是 2016 年)。并查看他们的东部时间 (ET)页面,了解包括例外情况在内的详细信息。
此外,特定区域是否遵守夏令时,如果是,数据边界是什么,会随着时间而变化。例如,在美国,DST 开始和结束日期在 2005 年末更改,从 2007 年开始生效:美国夏令时更改于 2005 年。意思是,即使您知道当前规则是+01:00在 3 月 13 日和 11 月 6 日之间将偏移量应用于 EST,那么如果您将UTC的DATETIME值转换2006-11-02 18:00:00为 ET,您会发现2006-11-02 14:00:00哪个是错误的,因为在 2006 年 DST 于 10 月结束28 日,使正确的东部时间为2006-11-02 13:00:00。
我的 DBA.StackExchange 回答中的其他解释:如何检查给定日期时间的时区?
如何在 SQL Server 2005 - 2014 中处理 DST(以及时区之间的转换)
我所知道的正确处理 DST 感知以及在不同时区之间转换的两种主要方法是:
Matt Johnson的SQL Server 时区支持项目:
这是一种纯 T-SQL 方法。请参阅上面链接的主页底部的自述文件(即项目名称)。请密切注意ConvertZone和SwitchZone函数,因为它们在实际时区之间进行转换,而不仅仅是偏移量!
另请注意,它指出:
支持 Microsoft SQL Server 2008 R2 及更高版本,包括 Azure SQL 数据库
SQLCLR:
使用DateTime.ToLocalTime和DateTime.ToUniversalTime在服务器的本地时区和 UTC 之间来回转换是相当简单的。这将从 SQL Server 2005 开始工作。
TimeZone由于TimeZone.ToLocalTime页面上显示以下警告,请远离具有相同名称方法的类:
ToLocalTime 方法仅识别本地时区的当前夏令时调整规则。因此,只有在最新的调整规则生效期间,才能保证准确返回特定UTC时间对应的本地时间。如果时间是受先前调整规则约束的历史日期和时间值,则它可能返回不准确的结果。
在时区之间转换有点棘手。有一个内置的 .NET 类可以处理这个问题,但它需要将调用程序集标记为UNSAFE对具有主机保护属性(即内存泄漏)的TimeZoneInfo类进行标记MayLeakOnAbort。人们已经使用过这个类,如果不非常频繁地调用它的方法可能没问题。但我确实看到至少有一个案例,有人报告在许多(数十万或数百万)行中运行时似乎是内存泄漏。
关于类中的安全ToLocalTime和ToUniversalTime方法DateTime:这些的预编译版本在我创建的SQL# SQLCLR 库中可用,但仅在完整版中可用(不在免费版中)。为了证明这 2 种方法确实有效,请考虑上述有关从 2007 年开始在美国发生的日期边界变化的情况:
SELECT SQL#.Date_ToLocalTime('2007-10-31 20:23:45') AS [CurrentRule],
SQL#.Date_ToLocalTime('2006-10-31 20:23:45') AS [PriorRule];
Run Code Online (Sandbox Code Playgroud)
返回:
CurrentRule PriorRule
2007-10-31 16:23:45.000 2006-10-31 15:23:45.000
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
7901 次 |
| 最近记录: |