简体   繁体   English

Cache.Add绝对到期-是否基于UTC?

[英]Cache.Add absolute expiration - UTC based or not?

The examples for Cache.Add uses DateTime.Now.Add to compute the expiration, ie it passes: Cache.Add的示例使用DateTime.Now.Add来计算到期时间,即,它传递:

 DateTime.Now.AddSeconds(60)

as the value of the absoluteExpiration parameter. 作为absoluteExpiration参数的值。

I'd have thought that computing it relative to DateTime.UtcNow would be more correct [as there is no ambiguity if Daylight Savings Time starts in the intervening time between now and the expiration point]. 我以为相对于DateTime.UtcNow计算它会更正确(因为如果夏时制从现在到到期点之间的间隔时间开始,这不会有任何歧义)。

Before the introduction of DateTimeKind , I'd have guessed that there's some ugly hacks in the cache management to make it do something appropriate if the time was not a UTC time. 在引入DateTimeKind之前,我猜想如果时间不是UTC时间,则缓存管理中会存在一些丑陋的骇客行为,以使其能够执行适当的操作。

In .NET 2.0 and later, I'm guessing that it should handle a DateTime calculated as DateTime.UtcNow.AddSeconds(60) correctly given that it has DateTime.Kind to use as an input in its inferences. 在.NET 2.0和更高版本,我猜测它应该处理DateTime作为计算DateTime.UtcNow.AddSeconds(60)正确地考虑到它具有DateTime.Kind作为其推论的输入来使用。

I've been confidently using DateTime.UtcNow as the base for years, but wasnt able to come up with a rationale that this is definitely the correct thing to do in the absence of anything pointing out the documentation has been highly misleading for 4+ years. 多年来,我一直自信地使用DateTime.UtcNow作为基础,但是在没有任何内容指出文档在四年多的时间里一直极具误导性的情况下,我无法得出这样的理由:这绝对是正确的做法。

The questions? 有什么问题吗

  1. Despite much bingage and googling I wasnt able to find any authoritative discussion on this from MS - can anyone locate something regarding this? 尽管进行了很多苦思冥想,但我还是无法从MS上找到任何权威的讨论-有人能找到与此相关的内容吗?
  2. Is there any reason why using UtcNow wouldnt be more correct and/or safe? 有什么理由为什么使用UtcNow会更正确和/或更安全?

(Yes, I could peruse the source and/or the Reflector'd source, but am looking for a full blow-by-blow lowdown!) (是的,我可以仔细研究光源和/或反射镜的光源,但我正在寻找一个完整的逐击式降低!)

I reported this bug on Microsoft Connect some time ago, but it's been closed as won't fix. 我前一段时间在Microsoft Connect上报告了此错误 ,但由于无法修复,因此已被关闭。

You still have a problem in .NET 2.0 if you specify your absolute expiration in local time. 如果您以本地时间指定绝对到期时间,则.NET 2.0中仍然存在问题。

During one hour at the end of daylight savings time, your local time is ambiguous, so you can get unexpected results, ie the absolute expiration can be one hour longer than expected. 在夏令时结束的一小时内,您的本地时间是模棱两可的,因此您会得到意想不到的结果,即,绝对到期时间可能比预期长一小时。

In Europe, daylight savings time ended at 02:00 on 25 October 2009. The sample below illustrates that if you placed an item in the cache at 01:59 with an expiration of 2 minutes, it would remain in the cache for one hour and two minutes. 在欧洲,夏时制时间于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());

The workaround for .NET 2.0 or later is to specify the absolute expiration time in UTC as pointed out by Ruben. .NET 2.0或更高版本的解决方法是如Ruben所指出的那样以UTC指定绝对到期时间。

Microsoft should perhaps be recommending to use UTC in the examples for absolute expiration, but I guess there is the potential for confusion since this recommendation is only valid for .NET 2.0 and later. Microsoft可能应该建议在示例中使用UTC来绝对过期,但是我想可能会造成混淆,因为该建议仅对.NET 2.0及更高版本有效。

EDIT 编辑

From the comments: 从评论:

But the exposure only occurs if the conversion happens during the overlap. 但是仅在重叠期间发生转换时才会发生曝光。 The single conversion actually taking place is when you lodge the item with Cache.Add 实际发生的一次转换是在您将项目存放在Cache.Add时

The problem will only happen if you insert an item in the cache with an AbsoluteExpiration time in local time during that one ambiguous hour at the end of daylight savings time. 仅当您在夏令时结束时的一个歧义小时内在本地时间中将具有AbsoluteExpiration时间的项目插入本地时间中时,才会发生此问题。

So for example, if your local time zone is Central European (GMT+1 in winter, GMT+2 in summer), and you execute the following code at 01:59:00 on 25 October 2009: 因此,例如,如果您的本地时区是中欧(冬季为GMT + 1,夏季为GMT + 2),而您在2009年10月25日的01:59:00执行以下代码:

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

then the item will remain in the cache for one hour and two minutes, rather than the two minutes you would normally expect. 那么该项目将在缓存中保留一小时零两分钟,而不是您通常希望的两分钟。 This can be a problem for some highly time-critical applications (eg stock ticker, airline departures board). 对于某些时间紧迫的应用程序(例如股票行情显示,航空公司出发板),这可能是一个问题。

What's happening here is (assuming European time, but the principle is the same for any time zone): 这里发生的是(假设是欧洲时间,但原理对于任何时区都是相同的):

  • DateTime.Now = 2009-10-25 01:59:00 local. DateTime.Now = 2009-10-25 01:59:00本地。 local=GMT+2, so UTC = 2009-10-24 23:59:00 local = GMT + 2,所以UTC = 2009-10-24 23:59:00

  • .AddMinutes(2) = 2009-10-25 02:01:00 local. .AddMinutes(2)= 2009-10-25 02:01:00本地。 local = GMT+1, so UTC = 2009-11-25 01:01:00 当地= GMT + 1,所以UTC = 2009-11-25 01:01:00

  • Cache.Add internally converts the expiration time to UTC (2009-11-25 01:01:00) so the expiration is one hour and two minutes ahead of the current UTC time (23:59:00). Cache.Add在内部将到期时间转换为UTC(2009-11-25 01:01:00),因此到期时间比当前UTC时间(23:59:00)提前一小时两分钟。

If you use DateTime.UtcNow in place of DateTime.Now, the cache expiration will be two minutes (.NET 2.0 or later): 如果使用DateTime.UtcNow代替DateTime.Now,则缓存过期将为两分钟(.NET 2.0或更高版本):

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

From the comments: 从评论:

Or am I missing something? 还是我错过了什么?

No you're not. 不你不是。 Your analysis is spot on and if your application is time-critical and runs during that period at the end of DST, you're right to be using DateTime.UtcNow. 您可以立即进行分析,并且如果您的应用程序是时间紧迫的并且在DST结束的那段时间内运行,那么使用DateTime.UtcNow是正确的。

The statement in Ruben's answer that: 鲁宾回答中的声明是:

you're safe to use either as long as the Kind on the time you supply is set 只要您设置了提供时间上的种类,您就可以安全使用

is incorrect. 是不正确的。

Cache.Add converts the expiration date to UTC before storing it. Cache.Add在存储之前将到期日期转换为UTC。

From Reflector (I've omitted most of the parameters to make it easier to read): 在Reflector中(为了方便阅读,我省略了大多数参数):

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

In CacheExpires.FlushExpiredItems , utcAbsoluteExpiration is compared to DateTime.UtcNow . CacheExpires.FlushExpiredItems ,将utcAbsoluteExpirationDateTime.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. 正如Joe在其答案中指出的那样 ,当缓存项的添加和过期时间超过夏令时时,这会导致意外行为。

[Highly derivative of insights from Jeff Sternal's answer, which I've +1'd in incomplete payment :D] [根据Jeff Sternal的回答得出的深刻见解,我在未付款项中+1:D]

It seems that in 1.1 (didnt look at 1.0 but I assume its similar), in the absence of a DateTime.Kind and having published examples with a DateTime.Now -relative time, they feel comfortable immediately calling ToUniversalTime() immediately. 似乎在1.1中(请看1.0,但我认为它与之类似),在没有DateTime.Kind且没有发布具有DateTime.Now相对时间的示例的情况下,他们感到立即立即调用ToUniversalTime()很舒服。

Hence... 因此...

  1. in 1.x, you'll end up with a mess if you [the API user] use DateTime.UtcNow (and there's a sensitivity to DST starting during the call to Cache.Add ) 在1.x中,如果[API用户]使用DateTime.UtcNow ,您将陷入混乱(并且在调用Cache.Add期间对DST敏感)

  2. in 2.0 [and 3.x], you're safe to use either as long as the Kind on the time you supply is set [which it normally would be if you got the time from DateTime.Now or UtcNow ]. 在2.0 [和3.x]中,只要设置了您提供的时间上的Kind (如果从DateTime.NowUtcNow获得时间,通常会是这样),就可以UtcNow [See Joe's comments and answer for full rationale] Definitely prefer UtcNow as ambiguity for 1 hour of DST switchover. [请参阅Joe的评论和答案以获取完整的理由]绝对更喜欢UtcNow因为它在DST切换1小时中存在歧义。

  3. The example stays as-is so people working against 1.x dont get misled [and people can go on pretending that DST is a wacky edge case :P]. 该示例保持原样,因此使用1.x的人们不会被误导[并且人们可以继续假装DST是一个古怪的边缘案例:P]。 [Ditto, as pointed out by Joe] But this is a very debatable stance as this can result in stuff staying in the cache for an extra hour. [Detto,如Joe所指出的]但是,这是一个值得商de的立场,因为这可能会使内容在缓存中保留额外的一个小时。

I'm still very interested to hear more details, including any from any Ponies out there. 我仍然很想听到更多详细信息,包括来自任何小马的信息。

EDIT: I realise from Joe's comments that I didn't explicitly call out the fact that it is definitely more correct to use UtcNow if using 2.0 or later as one is exposed to risk of the item being cached for an extra hour during the DST 'groundhog hour'. 编辑:我从乔的意见意识到,我并没有显式调用了一个事实,即它绝对更正确的使用UtcNow使用2.0或更高版本作为一个如果暴露于项目的风险DST“期间缓存一个小时土拨鼠小时”。 I also think the MS doc should point this fact out (with the proviso that they need to mention that this does not to apply to 1.1 [regardless of whether the page is marked 2.0+ specific]. Thanks Joe. 我也认为MS文档应该指出这一事实(附带条件是他们需要提到这不适用于1.1(无论页面是否标记为2.0+特定)。感谢Joe。

EDIT: Noda Time will have a neat wrapper to make this foolproof :D 编辑:野田时间将有一个整洁的包装,使这个万无一失:D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM