2010-05-17 18 views
11

¿Hay una manera más rápida que simplemente atrapar una excepción como la siguiente?¿Existe alguna manera más rápida de verificar si esta es una fecha válida?

try 
{ 
    date = new DateTime(model_.Date.Year, model_.Date.Month, (7 * multiplier) + (7 - dow) + 2); 
} 
catch (Exception) 
{ 
    // This is an invalid date 
} 
+2

¿Qué quiere decir, más rápido? Este código se ejecuta muy rápido a menos que tenga una fecha no válida. ¿O estás preguntando si hay una manera de hacer esto con menos código? –

Respuesta

15
String DateString = String.Format("{0}/{1}/{2}", model_.Date.Month, (7 * multiplier) + (7 - dow) + 2),model_.Date.Year); 

DateTime dateTime; 
if(DateTime.TryParse(DateString, out dateTime)) 
{ 
    // valid 
} 

Como el comentario señalado por GenericTypeTea, este código no se ejecutará más rápido que lo que tenemos ahora. Sin embargo, creo que ganas en legibilidad.

+0

@Michael G - no tengo una cadena de fecha. Solo tengo la información sobre – leora

+7

DateTime.TryParse arroja una excepción internamente de todos modos, esto no sería más rápido. – GenericTypeTea

+9

@GenericTypeTea - Eso es incorrecto. DateTime.TryParse() no ** arroja una excepción internamente! Sería más exacto pensar en ello como si DateTime.Parse() usa DateTime.TryParse() para decidir primero si se debe lanzar una excepción. –

2

Mira el método DateTime.TryParse

1

No sé acerca más rápido, pero

DateTime.TryParse() 

deberían hacer lo mismo.

Me interesaría si alguien pudiera decirme si esto es más rápido (en términos de tiempo de procesador) que la manera descrita en la pregunta.

-1

Si el mecanismo de análisis no es más rápido, puede usar el método un poco más detallado para verificar directamente las propiedades de su objeto modelo para los valores válidos.

9

Si su objetivo es evitar el uso de excepciones, se podría escribir un método de validación personalizada:

public bool IsValidDate(int year, int month, int multiplier, int dow) 
{ 
    if (year < 1 | year > 9999) { return false; } 

    if (month < 1 | month > 12) { return false; } 

    int day = 7 * multiplier + 7 - dow; 
    if (day < 1 | day > DateTime.DaysInMonth(year, month)) { return false; } 

    return true; 
} 

Esto realiza la mayor parte de las mismas validaciones como el constructor DateTime que está utilizando - que sólo omite la comprobación de ver si DateTime resultante sería menor que DateTime.MinValue o mayor que DateTime.MaxValue.

Si en su mayoría obtiene buenos valores, esto probablemente sería más lento en general: DateTime.DaysInMonth tiene que hacer muchas de las mismas cosas que el constructor de DateTime, por lo que agregaría una sobrecarga a todas las buenas fechas.

+0

Esto era exactamente lo que necesitaba, sin problemas de configuración regional – Evert

2

EDIT: ¡Woops! DateTime.TryParse no lanza una excepción internamente. ¡Estaba hablando por mis nalgas! De todos modos ...

DateTime.TryParse() lanzará una excepción internamente y provocará un resultado idéntico al código en su pregunta. Si la velocidad es importante, tendrá que escribir su propio método.

Esto puede parecer más código, pero creo que va a ser más rápido si usted está esperando un gran volumen de errores:

public bool GetDate(int year, int month, int day, out DateTime dateTime) 
{ 
    if (month > 0 && month <= 12) 
    { 
     int daysInMonth = DateTime.DaysInMonth(year, month); 
     if (day <= daysInMonth) 
     { 
      dateTime = new DateTime(year, month, day); 
      return true; 
     } 
    } 
    dateTime = new DateTime(); 
    return false; 
} 

Mi ejemplo anterior no se encargará de todos los casos (es decir, I' no estoy manejando años), pero te señalará en la dirección correcta.

+1

¿Por qué sería esto más rápido que TryParse()? –

+0

Me parece un poco redundante para un método para devolver un 'bool' ** y ** tener una variable de salida de tipo' Nullable '(¿por qué no solo' DateTime'?) ... –

+0

Para ser honesto, estaba operando bajo un concepto erróneo de DateTime.TryParse y pensó que arrojaba excepciones internamente dentro de sí mismo. He profundizado en el reflector y he visto lo que realmente hace y TryParse es probablemente más rápido si las fechas son perfectas cada vez. Sin embargo, creo que este método sería más rápido si hubiera fechas más incorrectas ... así que si se está revisando una gran cantidad de basura, este método sería mejor, pero si las fechas incorrectas son el caso límite, entonces TryParse sería mejor. – GenericTypeTea

0

Una cosa sin embargo: las excepciones son para casos excepcionales. Las cadenas Bogoformatted no son excepcionales sino esperadas, por lo que TryParse es más apropiado.

El uso de try/catch para verificar la validez es uso indebido y error de excepciones, especialmente con un catch-all catch (este último ya me hizo buscar horas por qué algo no funciona, y eso muchas veces).

5

Hmm ...creo que de esta manera: la clase model_ tiene una propiedad DateTime

model_.Date 

, así que no hay necesidad de validar el año & mes. La única parte difícil es el día del mes:

(7 * multiplier) + (7 - dow) + 2 

Así que de una manera muy rápida y eficiente para validar esta (que es mejor que lanzar y atrapar) es utilizar el método DateTime.DaysInMonth:

if ((multiplier <= 4) && 
    (DateTime.DaysInMonth(model_.Date.Year, model_.Date.Month) < 
     (7 * multiplier) + (7 - dow) + 2)) 
{ 
    // error: invalid days for the month/year combo... 
} 

Otra ventaja es que no necesita crear una instancia de un nuevo DateTime solo para validar esta información.

P.S. Actualizado el código para asegurarse de que multiplicador es < = 4. Esto sólo tiene sentido, ya que cualquier valor> = 5 fallará la prueba DaysInMonth ...

+0

+1 Mucho mejor IMO. –

+0

+1, solo eché un vistazo a la pregunta y pensé en publicar esto. Simplemente es perezoso hacerlo de otra manera. Deshágase de la mentalidad de nación .NET en su mejor momento. – Codesleuth

+0

+1 si la velocidad del algoritmo es realmente preocupante (la pregunta aún no está clara), una cláusula de guardia que verifique el multiplicador <= 4 sería importante. –

Cuestiones relacionadas