DateTime.ToUniversalTime 和 TimeZoneInfo.ConvertTimeToUtc 有什麼區別
我剛剛開始正確考慮推出一個 web 應用程序,該應用程序需要在使用者的一天開始時(比如早上 6 點)對他們做一些事情。也在他們生命的盡頭。
我一直在讀到人們說很多只是為了使用 .ToUniversalTime 以 UTC 儲存時間,但是當我嘗試這個時(我懷疑)它不起作用,它只是將時間移動了大約一個小時(我在英國,所以我認為這與從 GMT 到 UTC 的一些偏移有關,儘管這對我來說沒有意義,因為目前應該關閉夏令時)。
我在數據庫中有一個儲存使用者時區的欄位,所以當我開始使用 ConvertTimeToUtc 和 fromUtc 時,它開始做我期望它做的事情。雖然我再次不確定我是否必須自己建構一些邏輯來進行夏令時轉換,或者它應該為我做。
我主要想知道為什麼每個人都在談論.ToUniversalTime,因為它似乎對我沒有幫助,而且我不明白它怎麼可能知道將時間偏移到UTC,而第二種方式有道理。
有人可以解釋每種方法如何有用嗎?
如果您在不同時區的機器上執行程式碼,您的計算是否仍然有效?這就是人們將所有 DateTimes 儲存和處理為 UTC 的原因 - 它消除了任何歧義。您不需要儲存使用者的時區。任何地方的任何機器都可以從數據庫中提取日期並輕鬆地將其轉換為當地時間。
如果您將時間儲存在其他時區,那麼您必須將其拉出,計算與所需時區的偏移量,包括考慮夏令時和國際日期變更線的考慮。在您的情況下,您還儲存了額外的不必要資訊。
這兩者其實是有區別的。
在 .NET 3.5 及更低版本中,
Datetime.ToUniversalTime實現為:public DateTime ToUniversalTime() { return TimeZone.CurrentTimeZone.ToUniversalTime(this); }因為它使用了
TimeZone該類,所以它遇到了 MSDN 文件中提到的相同問題:該類
TimeZone僅支持本地時區的單一夏令時調整規則。因此,TimeZone該類可以準確地報告夏令時資訊或僅在最新調整規則生效期間在 UTC 和本地時間之間進行轉換。相比之下,TimeZoneInfo該類支持多個調整規則,這使得處理歷史時區數據成為可能。在 .NET 4.0 及更高版本中,
Datetime.ToUniversalTime實現為:public DateTime ToUniversalTime() { return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime); }修復了不支持歷史調整規則的問題,但是由於
NoThrowOnInvalidTimeflag的原因,和剛才呼叫不一樣TimeZoneInfo.ConvertimeToUtc。它呼叫的方法是一個帶有標誌的內部重載。公開版的方法用,而這個用的。
ConvertTimeToUtc``TimeZoneInfoOptions``TimeZoneInfoOptions.None``TimeZoneInfoOptions.NoThrowOnInvalidTime區別如下。時區設置為美國太平洋時間:
DateTime dt = new DateTime(2015, 3, 8, 2, 0, 0, DateTimeKind.Local); DateTime utc = dt.ToUniversalTime(); Console.WriteLine(utc); // "3/8/2015 10:00:00 AM"對比:
DateTime dt = new DateTime(2015, 3, 8, 2, 0, 0, DateTimeKind.Local); DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt); // throws exception! Console.WriteLine(utc);由於在這個日期,在這個時區,時間從 1:59:59 跳到 3:00:00,提供 2:00:00 的本地時間是無效的。正確的做法是拋出異常(如第二種情況)。但是,由於
DateTime.ToUniversalTime早期框架版本的現有合約不允許這樣做,因此框架選擇返回值而不是拋出。它選擇的值是根據使用標準時間偏移量計算的,就好像沒有發生 DST 轉換一樣。