40

Cache.Addの例はDateTime.Now.Add、有効期限を計算するために使用します。つまり、合格します。

 DateTime.Now.AddSeconds(60)

パラメータの値としてabsoluteExpiration

相対的に計算する方がより正確だと私は考えていたDateTime.UtcNowでしょう[現在と有効期限の間の中間時間にサマータイムが開始される場合、あいまいさはないため]。

が導入される前はDateTimeKind、時刻が UTC 時刻でない場合に適切な処理を行うために、キャッシュ管理にいくつかの醜いハックがあると推測していました。

.NET 2.0 以降では、推論で入力として使用する必要があるため、DateTime計算されたものをDateTime.UtcNow.AddSeconds(60)正しく処理する必要があると推測しています。DateTime.Kind

私は何年も自信を持ってDateTime.UtcNowベースとして使用してきましたが、ドキュメントが4年以上にわたって非常に誤解を招くものであったことを指摘するものが何もない場合、これが間違いなく正しいことであるという理論的根拠を思いつくことができませんでした.

質問?

  1. 多くのどんちゃん騒ぎとグーグルにもかかわらず、MSからこれに関する信頼できる議論を見つけることができませんでした.これに関して誰かが何かを見つけることができますか?
  2. UtcNow を使用することがより正確かつ/または安全ではない理由はありますか?

(はい、ソースおよび/またはリフレクターのソースを熟読できますが、完全な一撃ごとのローダウンを探しています!)

4

3 に答える 3

25

しばらく前にMicrosoftConnectでこのバグを報告しましたが、修正されないためクローズされました。

絶対有効期限を現地時間で指定した場合、.NET2.0でも問題が発生します。

夏時間の終わりの1時間の間、現地時間はあいまいであるため、予期しない結果が生じる可能性があります。つまり、絶対有効期限が予想より1時間長くなる可能性があります。

ヨーロッパでは、夏時間は2009年10月25日の02:00に終了しました。以下のサンプルは、アイテムを01:59に2分の有効期限でキャッシュに配置した場合、1時間キャッシュに残り、 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());

.NET 2.0以降の回避策は、Rubenが指摘したUTCでの絶対有効期限を指定することです。

Microsoftは、絶対有効期限の例でUTCを使用することを推奨しているはずですが、この推奨は.NET 2.0以降でのみ有効であるため、混乱する可能性があると思います。

編集

コメントから:

ただし、露出は、オーバーラップ中に変換が発生した場合にのみ発生します。実際に行われる単一の変換は、Cache.Addを使用してアイテムを提出するときです。

この問題は、夏時間の終わりのあいまいな1時間の間に、現地時間のAbsoluteExpiration時刻でアイテムをキャッシュに挿入した場合にのみ発生します。

たとえば、ローカルタイムゾーンが中央ヨーロッパ(冬はGMT + 1、夏はGMT + 2)で、2009年10月25日の01:59:00に次のコードを実行するとします。

DateTime absoluteExpiration = DateTime.Now.AddMinutes(2);
Cache.Add(... absoluteExpiration ...)

その後、アイテムは、通常予想される2分間ではなく、1時間2分間キャッシュに残ります。これは、非常にタイムクリティカルなアプリケーション(株式相場表示、航空会社の出発ボードなど)では問題になる可能性があります。

ここで起こっていることは次のとおりです(ヨーロッパの時間を想定していますが、原則はどのタイムゾーンでも同じです)。

  • DateTime.Now =2009-10-2501:59:00ローカル。local = GMT + 2、つまりUTC = 2009-10-24 23:59:00

  • .AddMinutes(2)=2009-10-2502:01:00ローカル。ローカル=GMT+ 1、つまりUTC = 2009-11-25 01:01:00

  • Cache.Addは、有効期限を内部でUTC(2009-11-25 01:01:00)に変換するため、有効期限は現在のUTC時刻(23:59:00)より1時間2分早くなります。

DateTime.Nowの代わりにDateTime.UtcNowを使用する場合、キャッシュの有効期限は2分になります(.NET 2.0以降)。

DateTime absoluteExpiration = DateTime.UtcNow.AddMinutes(2);
Cache.Add(... absoluteExpiration ...)

コメントから:

それとも私は何かが足りないのですか?

いいえ、違います。分析は的確であり、アプリケーションがタイムクリティカルであり、DSTの終了時にその期間中に実行される場合は、DateTime.UtcNowを使用する権利があります。

ルーベンの答えの声明は次のとおりです。

供給時の種類が設定されている限り、どちらでも安全に使用できます

間違っている。

于 2009-11-06T18:06:50.590 に答える
7

Cache.Add保存する前に、有効期限をUTCに変換します。

リフレクターから(読みやすくするためにほとんどのパラメーターを省略しました):

public object Add(... DateTime absoluteExpiration ...)
{
    DateTime utcAbsoluteExpiration = DateTimeUtil.ConvertToUniversalTime(absoluteExpiration);
    return this._cacheInternal.DoInsert(... utcAbsoluteExpiration ...);
}

In CacheExpires.FlushExpiredItems, utcAbsoluteExpiration is compared to DateTime.UtcNow. As Joe notes in his answer, this causes unexpected behavior when a cache item's addition and expiration span the end of daylight saving time.

于 2009-11-06T16:41:26.310 に答える
3

[不完全な支払いで+1したJeff Sternalの回答からの洞察の高度な派生物:D]

1.1 では (1.0 は見ていませんが、似ていると思います)、 a がなくDateTime.Kind、-relative 時間の例が公開されている場合DateTime.Now、彼らはすぐにすぐに電話をかけることを快適に感じているようToUniversalTime()です。

したがって...

  1. 1.x では、[API ユーザー] が使用すると混乱してしまいますDateTime.UtcNow(そして、への呼び出し中に開始される DST に対する感度がありますCache.Add) 。

  2. 2.0 [および 3.x] では、提供するオン タイムが設定されている限り、どちらを使用しても安全です[またはKindから時間を取得した場合は通常そうなります]。[完全な理論的根拠については、Joe のコメントと回答を参照してください]DateTime.NowUtcNowUtcNow

  3. この例は現状のままなので、1.x に対して作業を行っている人は誤解されません [そして、人々は DST が奇抜なエッジ ケースであると偽ることができます :P]。[同上、Joe が指摘したように] しかし、これは非常に議論の余地のあるスタンスです。

そこにいるポニーからの情報を含め、詳細を聞くことにまだ非常に興味があります.

編集: ジョーのコメントから、 2.0 以降を使用する場合は、DST のグラウンドホッグ中にアイテムが余分な時間キャッシュされるリスクにさらされているため、使用する方間違いなく正しいという事実を明示的に指摘しなかったことがわかります。UtcNow時間'。また、MS doc はこの事実を指摘する必要があると思います (ページが 2.0+ 固有とマークされているかどうかに関係なく、これが 1.1 には適用されないことを言及する必要があるという条件付きで)。Joe に感謝します。

編集:野田時間は、これを誰にでもできるようにするためのきちんとしたラッパーを持っています:D

于 2009-11-06T17:00:42.170 に答える