我前段时间在 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 是正确的。
鲁本回答中的陈述是:
只要设置了您提供的时间的种类,您就可以安全使用
是不正确的。