(此文章同時發表在本人微信公眾號“dotNET每日精華文章”,歡迎右邊二維碼來關註。) 題記:新年第一篇文章,就來談談關於時間的簡單技術問題:該用DateTime還是DateTimeOffset?該用Now還是UtcNow? 首先需要說明的是.NET中出現兩個保存時間的數據結構是由於歷史的原因。Da...
(此文章同時發表在本人微信公眾號“dotNET每日精華文章”,歡迎右邊二維碼來關註。)
題記:新年第一篇文章,就來談談關於時間的簡單技術問題:該用DateTime還是DateTimeOffset?該用Now還是UtcNow?
首先需要說明的是.NET中出現兩個保存時間的數據結構是由於歷史的原因。DateTime一開始就出現在.NET的基礎類型中;為瞭解決DateTime中的一些缺陷,又保證代碼能夠相容,就多出了一個DateTimeOffset。
DateTime只保存兩部分信息:Ticks和Kind。一個Tick是100納秒(1萬Tick等於1毫秒),Ticks記錄了從1/1/0001 12:00 AM到現在經過了多少100納秒。Kind保存的是DateTimeKind枚舉值,有Utc、Local和Unspecified 。Utc意味著Tick計數表示協調世界時間的數量,其不會受到夏令時或者時區的影響。Local表示本地時間的數量,會受到夏令時的影響。由於DateTime並不保存時區偏移,所以要獲得真正的UTC時間,就會檢查電腦當前的市區設置,那麼ToUniversalTime和ToLocalTime方法都會進行這樣的轉換。Kind的第三種值Unspecified,意味著我們不知道到底是本地時間還是UTC時間。所以這種情況只能表示年月日,時間無法精確表示。
DateTime除了存在這個問題,還會在進行比較的時候,其不會考慮Kind是UTC還是Local,從而導致錯誤。DateTime在進行字元串化的時候,對於某些標準格式也會出現問題(根源還是時區的問題),比如ToString("u")的時候,會直接把Local當作UTC來處理。
為瞭解決上述時區和轉換的問題,DateTimeOffset應運而生。它只保存Ticks,不保存Kind,且Ticks總是相對於UTC的值。
從官方文檔給出的建議來看,我們總是應該使用DateTimeOffset,只有僅僅表示日期和不需要關心時區的時候才使用DateTime。https://msdn.microsoft.com/en-us/library/bb384267.aspx
另外,在Stackoverflow上的這個回答http://stackoverflow.com/a/14268167,也很形象的描述了DateTimeOffset和DateTime的區別和優勢。簡而言之,DateTimeOffset是一種瞬時時間(即絕對時間),DateTime是一種曆法時間(即鐘錶時間)。
最後,這兩個數據類型都有Now和UtcNow兩個方法。Now用於獲取現在的時間,UtcNow獲取Utc的現在時間。而實際上,Now內部是先調用UtcNow,然後進行轉換得到。所以,在一般情況下,都應該使用UtcNow。
在文章結束的時候,給大家留個小問題,協調世界時間(Coordinated Universal Time)的簡寫為什麼是UTC,而不是CUT?下次文章公佈答案。