.net 缓存。添加绝对过期时间-是否基于UTC?
示例使用.net 缓存。添加绝对过期时间-是否基于UTC?,.net,asp.net,datetime,utc,system.web.caching,.net,Asp.net,Datetime,Utc,System.web.caching,示例使用DateTime.Now.Add计算过期时间,即过期时间: DateTime.Now.AddSeconds(60) 作为绝对过期参数的值 我本以为相对于DateTime.UtcNow计算它会更正确[因为如果夏令时从现在到到期点之间的中间时间开始,就不会有歧义] 在引入DateTimeKind之前,我猜想缓存管理中存在一些丑陋的漏洞,如果时间不是UTC时间,可以让它做一些适当的事情 在.NET2.0及更高版本中,我猜想它应该处理一个DateTime计算为DateTime.UtcNow.
DateTime.Now.Add
计算过期时间,即过期时间:
DateTime.Now.AddSeconds(60)
作为绝对过期
参数的值
我本以为相对于DateTime.UtcNow
计算它会更正确[因为如果夏令时从现在到到期点之间的中间时间开始,就不会有歧义]
在引入DateTimeKind
之前,我猜想缓存管理中存在一些丑陋的漏洞,如果时间不是UTC时间,可以让它做一些适当的事情
在.NET2.0及更高版本中,我猜想它应该处理一个DateTime
计算为DateTime.UtcNow.AddSeconds(60)
,因为它有DateTime.Kind
作为其推断中的输入
多年来,我一直自信地使用DateTime.UtcNow
作为基础,但在没有任何东西指出文档在4年多的时间里具有高度误导性的情况下,我无法提出这样做绝对正确的理由
问题是什么
(是的,我可以仔细阅读源代码和/或反射器的源代码,但我正在寻找一个完整的详细信息!)
缓存。Add
在存储之前将过期日期转换为UTC
从Reflector(为了便于阅读,我省略了大部分参数):
在
CacheExpires.FlusheExpiredItems
中,将utcAbsoluteExpiration
与DateTime.UtcNow
进行比较。例如,当缓存项的添加和过期跨越夏时制结束时,这会导致意外行为。[从Jeff Sternal的答案中获得的见解高度衍生,我在未完成支付中获得+1 d:d]
似乎在1.1中(我没有看1.0,但我假设它是类似的),在没有DateTime.Kind
的情况下,并且已经发布了带有DateTime.Now
-相对时间的示例,他们觉得立即调用ToUniversalTime()
很舒服
因此
DateTime.UtcNow
(并且在调用Cache.Add
的过程中对DST的启动有敏感度),那么最终会导致混乱种类
[如果您从DateTime.Now获得时间,通常情况下是这样的,现在
或UtcNow
]。[参见Joe的评论和回答,了解全部理由]对于1小时的DST切换,肯定更喜欢UtcNow
UtcNow肯定更正确,因为在DST“土拨鼠小时”期间,项目可能会被额外缓存一小时。我还认为微软文档应该指出这一事实(附带条件,他们需要提到这不适用于1.1[无论页面是否标记为2.0+特定],谢谢Joe
编辑:野田佳彦的时间将有一个整洁的包装,使这个万无一失:DI前一段时间,但它已被关闭,因为无法修复
如果在本地时间指定绝对过期时间,则.NET2.0中仍然存在问题
在夏令时结束时的一小时内,您的本地时间不明确,因此您可能会得到意外的结果,即绝对过期时间可能比预期时间长一小时
在欧洲,夏令时结束于2009年10月25日02:00。下面的示例说明,如果您在01:59将项目放置在缓存中,过期时间为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及更高版本
编辑
从评论中:
但只有当
转换发生在重叠期间。
实际需要的单个转换
地点是指您将物品寄存在
缓存。添加
只有在夏时制结束时的一个不明确的小时内,在缓存中插入一个在本地时间中具有绝对过期时间的项时,才会发生此问题
例如,如果您的本地时区是中欧(冬季为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 local.local=GMT+2,所以UTC=2009-10-24 23:59:00
- .AddMinutes(2)=2009-10-25 02:01:00 local.local=GMT+1,所以UTC=2009-11-25 01:01:00
- Cache.Add在内部将过期时间转换为UTC
DateTime absoluteExpiration = DateTime.Now.AddMinutes(2);
Cache.Add(... absoluteExpiration ...)
DateTime absoluteExpiration = DateTime.UtcNow.AddMinutes(2);
Cache.Add(... absoluteExpiration ...)