2009-03-04 8 views
6

Tengo dos fechas, una de una marca de tiempo y otra que estoy generando en el código. Necesito probar su igualdad, y me encantaría hacerlo sin demasiadas expresiones. He aquí un ejemplo de mis dos fechas:¿Cuál es la mejor manera de comparar la igualdad de dos DateTime en C# ... pero solo con cierta precisión?

DateTime expireTimeStampUTC = 
    DateTime.Parse(UTCValueFromDatabase)); 
DateTime expectedExpireTime = 
    DateTime.UtcNow.AddHours(NumberOfExpectedHoursInConfig); 

Esto es demasiado alta precisión de una prueba:

si (expireTimeStampUTC.Equals (expectedExpireTime)) {}

no me importa si Es exacto al segundo, solo a la hora.

¿Podría ser la mejor solución para hacer compuesto algo como esto:

if (expireTimeStampUTC.Date.Equals(expectedExpireTime.Date)) 
{ 
    if (!expireTimeStampUTC.Hour.Equals(expectedExpireTime.Hour)) 
    { 
     pass = false; 
    } 
} 

No estoy el más experimentado con C# ... ¿hay alguna manera de hacer esto elegentPackage?

Respuesta

10

Si el problema que está teniendo es debido a que es un tipo de base de datos, puede convertir a ese tipo y comparar allí, perdemos/ganamos aproximadamente milisegundos convirtiéndonos a SQLDateTimes en aproximadamente 1/3 de guardados de base de datos.

Si no es así, comparar la unidad que realmente se preocupan por:

DateTime dt1 = DateTime.UtcNow; 
DateTime dt2 = DateTime.UtcNow.AddMinutes(59); // or 1 or 61 for test values; 

// if the dates are in the same hour (12:10 == 12:50, 1:58 != 2:02) 
if(dt1.Hour == dt2.Hour) // result 

o si se preocupan de que están dentro de un lapso de tiempo horas

// if the dates are within one hour of each other (1:58 == 2:02, 3:30 != 4:45) 
if((dt1 - dt2).Duration() < TimeSpan.FromHours(1)) // result 

Aquí resta de fechas genera un lapso de tiempo, la la duración es el 'valor absoluto' y luego creamos el límite explícitamente desde una unidad que nos importa (FromHours) y lo comparamos.

La última línea es tan limpia como puedo pensar para hacer la igualdad dentro de un lapso de tiempo determinado.

+0

En realidad, creo que este es en realidad un mejor estilo. Creo que está más claro lo que está sucediendo. Nunca antes he cambiado el token de "respuesta correcta", pero creo que en este caso, esta es la mejor solución. – danieltalsky

+0

Bastante justo. Creo que es seis y media docena el otro. La sintaxis de "Duración()" podría ser más legible, pero tiene la carga (por cierto insignificante) de actualizar un TimeSpan en ambos lados de la comparación. –

1

Construya nuevos objetos DateTime y compárelos. En C#, hay muy poca penalización por construir objetos "desechables" de esta manera.

+0

De nuevo, me gustaría ver un ejemplo en el código. – danieltalsky

6

¿Qué le parece encontrar la diferencia entre las dos horas y ver si está por debajo de cierto umbral (digamos 3600 segundos por una hora)?

var diff = expireTimeStamp.Subtract(expectedExpireTime).TotalSeconds; 
pass = Math.Abs(diff) < 3600; 
+0

Excelente ... esa fue la respuesta tan estúpidamente obvia que me daría una patada por no pensar en ello. Gracias. Y con una muestra de código también. Mágico. – danieltalsky

+0

Aunque, no "var" en C#;) – danieltalsky

+1

¡Quizás no en * su * C#! Es hora de actualizar a Visual Studio 2008, amigo! :) –

4

Restarlos. Compruebe si el TimeSpan resultante se encuentra dentro de un cierto rango máximo.

+0

Los valores de fecha y hora son compatibles con la operación de resta. obtienes un TimeSpan, compruebas si es más pequeño que el intervalo especificado. – Cheeso

+1

Eso es más o menos lo que acabo de decir. – recursive

1

Tuve el problema al intentar escribir pruebas unitarias que cometían objetos comerciales recuperados. Estaba intentando usar la propiedad "StartTime" de mi objeto para asegurarme de que el objeto pueda ser recuperado y encuentre este problema. El valor "StartTime" confirmado en la base de datos perdió 6 dígitos de precisión en el valor de Ticks.

Así es como reescribí mi condición de prueba para que mi prueba funcione correctamente y pase. La línea relevante es la penúltima línea de bloque.

DateTime start = DateTime.Now; 
NewEventInfo testEvent1 = FakeEvent("test01action", start); //plus other params for testing 
mServiceClient.AddEvent(testEvent1); 

EventInfo[] eventInfos = null; //code to get back events within time window 

Assert.IsNotEmpty(eventInfos); 
Assert.GreaterOrEqual(eventInfos.Length, 1); 

EventInfo resultEvent1 = eventInfos.FirstOrDefault(e => 
e.Action == "test01action" && 
Math.Abs(e.StartTime.Subtract(testEvent1.StartTime).TotalMilliseconds) < 1000); //checks dates are within 1 sec 
Assert.IsNotNull(resultEvent1); 

Esta manera de que pudiera estar seguro de que el objeto era el cometido por la prueba de la unidad, ya que la propiedad EventInfo.StartTime sólo utiliza los tiempos de la fecha con precisión de 1 segundo.

EDITAR: Agregó Math.Abs ​​(alrededor de DateTime diff) para asegurar que el valor absoluto se compara con 1000.

Cuestiones relacionadas