Sql-Server

SQL Server 2014 現在考慮夏令時了嗎?

  • December 20, 2018

我的電腦/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

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,因為該偏移量目前是您伺服器的 TimeZone(它確實會改變,否則它不會顯示大約半年的正確時間)和 UTC 之間的真正差異,它在一年中不會改變。然而,這確實表明了 DST 感知:它是 DST 感知的作業系統,這就是伺服器的目前時間如何根據 DST 變化。

支持 DST 意味著在切換 TimeZone 時可以考慮以前期間*和其他 TimeZone 的 DST 日期邊界。這需要了解時區。但是,SQL Server(至少在 SQL Server 2016 之前)沒有 TimeZones 的概念。偏移量就是這樣:距離 UTC 的特定小時數和分鐘數。相比之下,TimeZone 是一條規則,它規定了一個特定的偏移量如果曾經應用夏令時(某些 TimeZones 不參與 DST),*如果應用 DST,那麼這些日期邊界是什麼(這是法律問題並且可以轉換時間,每個地區)。

因此,支持 DST 意味著您可以將過去的日期轉換為您目前的時區任何兩個時區之間的任何日期,這兩個時區都不是伺服器的目前時區。這意味著,支持 DST 的 SQL Server 表明您可以從以下位置進行轉換:

  • UTC 到東部時間(您的伺服器的目前時區),一年中的任何日期,20 年前,並獲得正確的時間,即使在此期間美國的 DST 日期邊界發生了變化。但是你不能,因為你只能計算目前的偏移量,-04:00而且沒有辦法確定那個偏移量是什麼時候-05:00
  • 任何日期的任何非東部時區到任何其他非東部時區,並獲得正確的時間。這是不可能的,因為沒有 TimeZone 圖表詳細說明哪個 TimeZone 是哪個日期的偏移量,包括這些日期邊界的歷史變化,因此任何特定年份的任何特定日期都將得到正確調整。

更多資訊和一些例子

如上所述,時區偏移不是時區:它們只是時區的屬性。意思是,“美國/東部”(又名“美國/紐約”)時區(即 EST / EDT)不被辨識-04:00-05:00; 它是一個與東部和西部有邊界的區域,基本偏移量為-05:00,並參與夏令時,因此具有偏移量 –+01:00以及何時應用該 DST 偏移量的特定開始日期和結束日期. 您可以在TimeZoneDB.com上查看資訊。

此時區資訊的主數據庫由 Internet 名稱分配機構 (IANA) 維護,可在以下位置找到:

http://www.iana.org/time-zones

時區資訊由各個政府確定。一些國家參加夏令時,其他國家不參加。不同國家/州的一些城市選擇加入或退出父區域規則。請參閱TimeAndDate.com 上的2016 年全球夏令時頁面,了解全球各種開始和結束日期的圖表(至少 2016 年)。並查看他們的東部時間 (ET)頁面,了解包括例外情況在內的詳細資訊。

此外,特定區域是否遵守 DST,如果是,數據邊界是什麼,隨著時間的推移而變化。例如,在美國,DST 的開始和結束日期在 2005 年底發生了變化,從 2007 年開始生效:US Daylight Saving Time Changed in 2005。意思是,即使您知道目前規則是+01:00在 3 月 13 日至 11 月 6 日之間將偏移量應用於 EST,那麼如果您將DATETIME2006-11-02 18:00:00從 UTC 轉換為 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 意識以及在不同時區之間轉換的兩種主要方法是:

  1. Matt JohnsonSQL Server 時區支持項目:

這是一種純 T-SQL 方法。請參閱上面連結的首頁底部的自述文件(即項目名稱)。密切注意ConvertZoneSwitchZone函式,因為它們在實際時區之間轉換,而不僅僅是偏移!

另請注意,它指出:

支持 Microsoft SQL Server 2008 R2 及更高版本,包括 Azure SQL 數據庫

  1. SQLCLR:

使用DateTime.ToLocalTimeDateTime.ToUniversalTime在伺服器的本地時區和 UTC 之間來迴轉換非常簡單。這將從 SQL Server 2005 開始工作。

TimeZone由於TimeZone.ToLocalTime頁面上顯示以下警告,請遠離具有相同名稱的方法的類:

ToLocalTime 方法僅辨識本地時區的目前夏令時調整規則。因此,只有在最新調整規則生效期間,才能保證準確返回特定UTC時間對應的本地時間。如果時間是受先前調整規則約束的歷史日期和時間值,它可能會返回不准確的結果。

在時區之間轉換有點棘手。有一個內置的 .NET 類可以處理這個問題,但它需要將呼叫程序集標記為UNSAFE對具有主機保護屬性的TimeZoneInfoMayLeakOnAbort類(即記憶體洩漏)。人們已經使用過這個類,如果不經常呼叫它的方法,它可能會很好。但我確實看到至少有一個案例有人報告在跨許多(數十萬或數百萬)行執行時似乎出現了記憶體洩漏。

關於類中的安全ToLocalTimeToUniversalTime方法DateTime:這些的預編譯版本在我創建的SQL# SQLCLR 庫中可用,但僅限於完整版(不是免費版)。為了證明這兩種方法確實有效,請考慮上面提到的關於美國從 2007 年開始發生的日期邊界變化的情況:

SELECT SQL#.Date_ToLocalTime('2007-10-31 20:23:45') AS [CurrentRule],
      SQL#.Date_ToLocalTime('2006-10-31 20:23:45') AS [PriorRule];

回報:

CurrentRule                PriorRule
2007-10-31 16:23:45.000    2006-10-31 15:23:45.000

引用自:https://dba.stackexchange.com/questions/143417