Cache.Add 絕對過期 - 是否基於 UTC?
Cache.Add的範例用於計算
DateTime.Now.Add過期時間,即通過:DateTime.Now.AddSeconds(60)作為
absoluteExpiration參數的值。我曾認為相對於它的計算
DateTime.UtcNow會更正確[因為如果夏令時在現在和到期點之間的中間時間開始,則沒有歧義]。在引入
DateTimeKind.在 .NET 2.0 及更高版本中,我猜測它應該正確處理
DateTime計算,DateTime.UtcNow.AddSeconds(60)因為它必須DateTime.Kind在其推理中用作輸入。多年來,我一直自信地使用
DateTime.UtcNow它作為基礎,但在沒有任何東西指出該文件已經高度誤導 4 年多的情況下,這絕對是正確的做法。問題?
- 儘管有很多狂歡和Google搜尋,但我無法從 MS 找到任何關於此的權威討論 - 任何人都可以找到有關此的內容嗎?
- 為什麼使用 UtcNow 不會更正確和/或更安全?
(是的,我可以仔細閱讀源和/或 Reflector 的源,但我正在尋找一個完整的逐個打擊的內幕!)
我前段時間在 Microsoft Connect 上報告了這個錯誤,但由於無法修復,它已被關閉。
如果您在本地時間指定絕對到期時間,您在 .NET 2.0 中仍然存在問題。
在夏令時結束的一小時內,您的當地時間是不明確的,因此您可能會得到意想不到的結果,即絕對到期時間可能比預期的時間長一小時。
在歐洲,夏令時於 2009 年 10 月 25 日 02:00 結束。下面的範例說明,如果您在 01:59 將項目放入記憶體中並過期 2 分鐘,它將在記憶體中保留一小時,然後2分鐘。
DateTime startTime = new DateTime(2009, 10, 25, 1, 59,0); DateTime endTime = startTime.AddMinutes(2); // end time is two minutes after start time DateTime startUtcTime = startTime.ToUniversalTime(); DateTime endUtcTime = endTime.ToUniversalTime(); // end UTC time is one hour and two minutes after start UTC time Console.WriteLine("Start UTC time = " + startUtcTime.ToString()); Console.WriteLine("End UTC time = " + endUtcTime.ToString());如 Ruben 所指出的,.NET 2.0 或更高版本的解決方法是在 UTC 中指定絕對過期時間。
Microsoft 可能應該建議在範例中使用 UTC 來表示絕對過期,但我想這可能會造成混淆,因為該建議僅對 .NET 2.0 及更高版本有效。
編輯
從評論:
但是只有在重疊期間發生轉換時才會發生曝光。實際發生的單一轉換是當您使用 Cache.Add 送出項目時
僅當您在夏令時結束時的一個模棱兩可的小時內將具有本地時間的 AbsoluteExpiration 時間的項目插入記憶體時,才會發生此問題。
例如,如果您的本地時區是中歐(冬季 GMT+1,夏季 GMT+2),並且您在 2009 年 10 月 25 日 01:59:00 執行以下程式碼:
DateTime absoluteExpiration = DateTime.Now.AddMinutes(2); Cache.Add(... absoluteExpiration ...)那麼該項目將在記憶體中保留一小時兩分鐘,而不是您通常期望的兩分鐘。這對於一些對時間要求非常嚴格的應用程序(例如股票行情、航空公司離港板)來說可能是個問題。
這裡發生的事情是(假設歐洲時間,但任何時區的原則都是相同的):
- DateTime.Now = 2009-10-25 01:59:00 本地。本地=GMT+2,所以 UTC = 2009-10-24 23:59:00
- .AddMinutes(2) = 2009-10-25 02:01:00 本地。本地 = GMT+1,所以 UTC = 2009-11-25 01:01:00
- Cache.Add 在內部將過期時間轉換為 UTC (2009-11-25 01:01:00),因此過期時間比目前 UTC 時間 (23:59:00) 提前一小時兩分鐘。
如果您使用 DateTime.UtcNow 代替 DateTime.Now,則記憶體到期時間為兩分鐘(.NET 2.0 或更高版本):
DateTime absoluteExpiration = DateTime.UtcNow.AddMinutes(2); Cache.Add(... absoluteExpiration ...)從評論:
還是我錯過了什麼?
不你不是。您的分析是正確的,如果您的應用程序對時間要求很高,並且在 DST 結束時的這段時間內執行,那麼您使用 DateTime.UtcNow 是正確的。
魯本回答中的陳述是:
只要設置了您提供的時間的種類,您就可以安全使用
是不正確的。