.net asp.net datetime utc system.web.caching

.net - Caché.Agregar expiración absoluta-UTC basado o no?



asp.net datetime (3)

Los ejemplos de Cache.Add utilizan DateTime.Now.Add para calcular la caducidad, es decir, pasa:

DateTime.Now.AddSeconds(60)

como el valor del parámetro absoluteExpiration .

Habría pensado que computarlo en relación con DateTime.UtcNow sería más correcto [ya que no hay ambigüedad si el horario de verano comienza en el momento intermedio entre este momento y el punto de vencimiento].

Antes de la introducción de DateTimeKind , habría adivinado que hay algunos trucos feos en la administración del caché para que haga algo apropiado si la hora no fuera la hora UTC.

En .NET 2.0 y versiones posteriores, supongo que debería manejar un DateTime calculado como DateTime.UtcNow.AddSeconds(60) correctamente, dado que tiene DateTime.Kind para usar como una entrada en sus inferencias.

He estado utilizando con confianza DateTime.UtcNow como la base durante años, pero no pude encontrar una justificación de que esto sea definitivamente lo correcto en ausencia de algo que indique que la documentación ha sido altamente engañosa por más de 4 años. .

¿Las preguntas?

  1. A pesar de mucho bingage y Google, no pude encontrar ninguna discusión autorizada sobre esto por parte de MS. ¿Alguien puede encontrar algo al respecto?
  2. ¿Hay alguna razón por la cual usar UtcNow no sería más correcto y / o seguro?

(Sí, podría leer detenidamente la fuente y / o la fuente del Reflector''d, ¡pero estoy buscando un golpe completo golpe por golpe!)


[Altamente derivada de las ideas de la respuesta de Jeff Sternal, que hice +1 en pago incompleto: D]

Parece que en 1.1 (no miré 1.0, pero asumo que es similar), en ausencia de un DateTime.Kind y habiendo publicado ejemplos con un DateTime.Now , se sienten cómodos inmediatamente llamando a ToUniversalTime() inmediatamente.

Por lo tanto...

  1. en 1.x, terminará con un desastre si [el usuario de la API] usa DateTime.UtcNow (y hay una sensibilidad al inicio de DST durante la llamada a Cache.Add )

  2. en 2.0 [y 3.x], puede usarlo con seguridad siempre y cuando se establezca la Kind en el momento de la oferta [que sería normalmente si obtuviera la hora de DateTime.Now o UtcNow ]. [Vea los comentarios de Joe y responda para una explicación completa] Definitivamente prefiero UtcNow como ambigüedad por 1 hora de cambio de horario de verano.

  3. El ejemplo se mantiene como está, así que las personas que trabajan en contra de 1.x no se engañen [y la gente puede seguir fingiendo que el horario de verano es un caso extravagante: P]. [Ídem, como lo señaló Joe] Pero esta es una postura muy discutible ya que esto puede hacer que las cosas permanezcan en el caché por una hora extra.

Todavía estoy muy interesado en escuchar más detalles, incluidos los de cualquier Ponis que haya.

EDITAR: Me doy cuenta de los comentarios de Joe que no UtcNow explícitamente el hecho de que definitivamente es más correcto usar UtcNow si se usa 2.0 o posterior, ya que uno está expuesto al riesgo de que el elemento se almacene en caché durante una hora adicional durante el DST '' hora de la marmota ''. También creo que el MS doc debe señalar este hecho (con la condición de que deben mencionar que esto no se aplica a 1.1 [independientemente de si la página está marcada como 2.0+ específica]. Gracias, Joe.

EDITAR: Noda Time tendrá un envoltorio limpio para hacer esto a toda prueba: D


Notifiqué este error en Microsoft Connect hace algún tiempo, pero se cerró porque no se solucionó.

Todavía tiene un problema en .NET 2.0 si especifica su vencimiento absoluto en la hora local.

Durante una hora al final del horario de verano, su hora local es ambigua, por lo que puede obtener resultados inesperados, es decir, la caducidad absoluta puede ser una hora más de lo esperado.

En Europa, el horario de verano finalizó a las 02:00 del 25 de octubre de 2009. El siguiente ejemplo muestra que si coloca un elemento en el caché a las 01:59 con un vencimiento de 2 minutos, permanecerá en el caché durante una hora y dos minutos.

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());

La solución para .NET 2.0 o posterior es especificar el tiempo de vencimiento absoluto en UTC como lo señala Ruben.

Microsoft quizás debería recomendar el uso de UTC en los ejemplos de vencimiento absoluto, pero creo que existe la posibilidad de confusión, ya que esta recomendación solo es válida para .NET 2.0 y versiones posteriores.

EDITAR

De los comentarios:

Pero la exposición solo ocurre si la conversión ocurre durante la superposición. La conversión única que realmente se está produciendo es cuando se aloja el elemento con Cache.Add

El problema solo ocurrirá si inserta un elemento en el caché con una hora AbsoluteExpiration en la hora local durante esa hora ambigua al final del horario de verano.

Por ejemplo, si su zona horaria local es Europa Central (GMT + 1 en invierno, GMT + 2 en verano) y ejecuta el siguiente código a las 01:59:00 del 25 de octubre de 2009:

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

entonces el elemento permanecerá en el caché durante una hora y dos minutos, en lugar de los dos minutos que normalmente esperaría. Esto puede ser un problema para algunas aplicaciones altamente críticas en el tiempo (por ejemplo, indicador de cotización de acciones, tablero de salidas de aerolíneas).

Lo que está sucediendo aquí es (asumiendo la hora europea, pero el principio es el mismo para cualquier zona horaria):

  • DateTime.Now = 2009-10-25 01:59:00 local. local = GMT + 2, entonces UTC = 2009-10-24 23:59:00

  • .AddMinutes (2) = 2009-10-25 02:01:00 local. local = GMT + 1, entonces UTC = 2009-11-25 01:01:00

  • Caché. Agregar internamente convierte el tiempo de vencimiento a UTC (2009-11-25 01:01:00) por lo que el vencimiento es una hora y dos minutos antes de la hora UTC actual (23:59:00).

Si usa DateTime.UtcNow en lugar de DateTime.Ahora, la caducidad del caché será de dos minutos (.NET 2.0 o posterior):

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

De los comentarios:

¿O me estoy perdiendo algo?

No tu no eres. Su análisis es acertado y si su aplicación es crítica en el tiempo y se ejecuta durante ese período al final del horario de verano, tiene derecho a usar DateTime.UtcNow.

La declaración en la respuesta de Ruben que:

Puede usarlo con total seguridad ya que el Tipo en el momento en que lo suministre está configurado

Es incorrecto.


Cache.Add convierte la fecha de caducidad en UTC antes de almacenarla.

De Reflector (he omitido la mayoría de los parámetros para que sea más fácil de leer):

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

En CacheExpires.FlushExpiredItems , utcAbsoluteExpiration se compara con DateTime.UtcNow . Como señala Joe en su respuesta , esto causa un comportamiento inesperado cuando la adición y la expiración de un elemento de caché se extienden al final del horario de verano.