Cache.Add Absolute Expiration - UTC на основе или нет?
-
18-09-2019 - |
Вопрос
Примеры для 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+ лет.
Вопросы?
- Несмотря на много бингаж и гуглей, я не смог найти никакой авторитетной дискуссии об этом от MS - кто -нибудь может найти что -то об этом?
- Есть ли причина, по которой использование UTCNOW не будет более правильным и/или безопасным?
(Да, я мог бы просмотреть источник и/или источник отражателя, но ищу полное снижение спуска!)
Решение
я сообщил об этой ошибке на Microsoft Connect Некоторое время назад, но он был закрыт, как не исправят.
У вас все еще есть проблема в .NET 2.0, если вы указали свое абсолютное истечение в локальное время.
В течение одного часа в конце дневного времени сэкономить ваше местное время неоднозначно, так что вы можете получить неожиданные результаты, то есть абсолютное истечение может быть на час дольше, чем ожидалось.
В Европе время экономии летнего света закончилось в 02:00 25 октября 2009 года. Приведенный ниже образец показывает, что если вы поместите элемент в кэше в 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 или более поздней, чтобы указать абсолютное время истечения срока действия в UTC, как указано Рубен.
Microsoft, возможно, должна рекомендовать использовать UTC в примерах для абсолютного срока действия, но я думаю, что есть потенциал для путаницы, поскольку эта рекомендация действительна только для .NET 2.0 и позже.
РЕДАКТИРОВАТЬ
Из комментариев:
Но воздействие происходит только в том случае, если преобразование происходит во время перекрытия. На самом деле единственное преобразование происходит, когда вы подаете элемент с помощью cache.add
Проблема произойдет только в том случае, если вы вставите элемент в кеш со временем AbsoluteExpiration в местное время в этот один неоднозначный час в конце дневного времени сэкономить.
Так, например, если ваш местный часовой пояс является центральной европейской (GMT+1 зимой, GMT+2 летом), и вы выполняете следующий код в 01:59:00 25 октября 2009 года:
DateTime absoluteExpiration = DateTime.Now.AddMinutes(2);
Cache.Add(... absoluteExpiration ...)
Затем предмет останется в кеше в течение одного часа и двух минут, а не в две минуты, которые вы обычно ожидаете. Это может быть проблемой для некоторых применений с очень критическим во времени (например, аккета аккета, Совет по вылете авиакомпании).
Здесь происходит (при условии европейского времени, но принцип одинаково для любого часового пояса):
DateTime.now = 2009-10-25 01:59:00 локально. Local = GMT+2, SO UTC = 2009-10-24 23:59:00
.Addminutes (2) = 2009-10-25 02:01:00 локально. Local = GMT+1, SO UTC = 2009-11-25 01:01:00
Cache.Add Внутренне преобразует время истечения в UTC (2009-11-25 01:01:00), поэтому истечение составляет один час и на две минуты опережать текущее время UTC (23:59:00).
Если вы используете datetime.utcnow вместо DateTime.
DateTime absoluteExpiration = DateTime.UtcNow.AddMinutes(2);
Cache.Add(... absoluteExpiration ...)
Из комментариев:
Или я что -то упускаю?
Нет, нет. Ваш анализ находится на месте, и если ваше приложение является критическим по времени и работает в течение этого периода в конце DST, вы правы, используя DateTime.Utcnow.
Утверждение в ответе Рубена:
Вы безопасны для использования, пока не установлено время, которое вы поставляете
это неверно.
Другие советы
Cache.Add
преобразует дату истечения срока действия в UTC, прежде чем хранить его.
От отражателя (я пропустил большинство параметров, чтобы облегчить чтение):
public object Add(... DateTime absoluteExpiration ...)
{
DateTime utcAbsoluteExpiration = DateTimeUtil.ConvertToUniversalTime(absoluteExpiration);
return this._cacheInternal.DoInsert(... utcAbsoluteExpiration ...);
}
В CacheExpires.FlushExpiredItems
, utcAbsoluteExpiration
сравнивается с DateTime.UtcNow
. Анкет В качестве Джо отмечает в своем ответе, это вызывает неожиданное поведение, когда добавление и истечение срока действия элемента кеша охватывают конец дневного света.
Высокопроизвольная идея от ответа Джеффа Стернала, который я +1'd в неполном платеже: D
Кажется, что в 1.1 (не смотрел на 1.0, но я предполагаю, что это похоже), в отсутствие DateTime.Kind
и опубликовать примеры с DateTime.Now
-Потранное время, они чувствуют себя комфортно сразу же звонить ToUniversalTime()
немедленно.
Следовательно...
В 1.x вы получите беспорядок, если вы [пользователь API] используете
DateTime.UtcNow
(И есть чувствительность к DST, начинающемуся во время вызова кCache.Add
)в 2.0 [и 3.x], вы безопасны для использования, пока
Kind
В то время, когда вы поставляете, [что обычно было бы, если бы у вас было время отDateTime.Now
или жеUtcNow
] [См. Комментарии и ответ Джо для полного обоснования] Определенно предпочитаютUtcNow
как двусмысленность в течение 1 часа переключения DST.Пример остается как есть, поэтому люди, работающие с 1.x, не вводятся в заблуждение [и люди могут продолжать притворяться, что DST-это дурацкий крайний случай: P]. [То же самое, как указал Джо], но это очень спорная позиция, так как это может привести к тому, что вещи остаются в кеше в течение дополнительного часа.
Мне все еще очень интересно услышать более подробную информацию, в том числе любую от любых пони.
РЕДАКТИРОВАТЬ: Из комментариев Джо я понимаю, что я явно не назвал тот факт, что это является Определенно более правильно в использовании UtcNow
При использовании 2,0 или более позднего года, когда один подвергается риску того, что предмет кэширован в течение дополнительного часа в течение «Часа сурка». Я также думаю, что MS DOC должен указать на этот факт (с условием, что им нужно упомянуть, что это не должно применяться к 1.1 [независимо от того, отмечена ли страница.
РЕДАКТИРОВАТЬ: У Noda Time будет аккуратная обертка, чтобы сделать эту надежную: D