¿Cómo validar una fecha y hora en C #?

118

Dudo que sea el único que ha encontrado esta solución, pero si tiene una mejor, publíquela aquí. Simplemente quiero dejar esta pregunta aquí para que yo y otros podamos buscarla más tarde.

Necesitaba saber si se había ingresado una fecha válida en un cuadro de texto y este es el código que se me ocurrió. Disparo esto cuando el foco sale del cuadro de texto.

try
{
    DateTime.Parse(startDateTextBox.Text);
}
catch
{
    startDateTextBox.Text = DateTime.Today.ToShortDateString();
}
Mate
fuente
1
<sarcasmo> a juzgar por las respuestas, creo que debería usar TryParse </sarcasm> Gracias por las excelentes respuestas chicos. Ni siquiera había pensado en TryParse
Matt
2
Un ejemplo de una pregunta fácil de buscar en Google que, si alguien la hiciera hoy, se cerraría injustamente por no tener "suficiente investigación".
live-love
1
aquí hay una manera fácil de hacer esto sin usar funciones especiales: < stackoverflow.com/questions/14917203/… >
Zameer
2
Trabajar con DateTimes siempre es un fastidio. Gracias
Gonzo345

Respuestas:

269
DateTime.TryParse

Creo que esto es más rápido y significa que no tienes que usar intentos / capturas feos :)

p.ej

DateTime temp;
if(DateTime.TryParse(startDateTextBox.Text, out temp))
{
  // Yay :)
}
else
{
  // Aww.. :(
}
qui
fuente
2
Corrígeme si me equivoco, pero en C # (a diferencia de, digamos, JavaScript), ¿una rama if / else no requiere llaves? No me malinterpretes, no estoy tratando de escudriñar, es una respuesta fantástica y estoy haciendo +1 porque me ayudó, pero pensé que, dado que nunca se sabe qué nuevos usuarios futuros ven cuando ven respuestas ya publicadas, esto podría confundirlos. Por supuesto, si tiene problemas con las llaves en C #, esta pregunta sería la menor de sus preocupaciones ...
VoidKing
2
@VoidKing Tienes razón sobre las llaves, pero si solo tienes 1 declaración en ese bloque, no tienes que usarlas. Esto también se aplica en otros idiomas, pero puedo ver cómo esto puede ser engañoso para los codificadores más nuevos.
D.Galvez
2
@ D.Galvez Disculpe que llegue tarde a la fiesta, pero ¿es una buena práctica incluir los corchetes incluso si solo hay una declaración? Esta podría ser una situación en la que la preferencia personal sea más importante, y en ese caso, creo que incluirlos es bastante bueno simplemente por la legibilidad y la coherencia.
Nick
2
Poco sabía hace 6 años que se produciría tal debate sobre los corchetes.
qui
Es posible acortar la inicialización de la variable con if(DateTime.TryParse(startDateTextBox.Text, out var temp)):)
Alexandre Daubricourt
61

No use excepciones para el control de flujo. Utilice DateTime.TryParse y DateTime.TryParseExact . Personalmente prefiero TryParseExact con un formato específico, pero creo que hay ocasiones en las que TryParse es mejor. Ejemplo de uso basado en su código original:

DateTime value;
if (!DateTime.TryParse(startDateTextBox.Text, out value))
{
    startDateTextox.Text = DateTime.Today.ToShortDateString();
}

Razones para preferir este enfoque:

  • Código más claro (dice lo que quiere hacer)
  • Mejor rendimiento que detectar y tragar excepciones
  • Esto no detecta las excepciones de forma inapropiada, por ejemplo, OutOfMemoryException, ThreadInterruptedException. (Su código actual podría arreglarse para evitar esto simplemente capturando la excepción relevante, pero usar TryParse aún sería mejor).
Jon Skeet
fuente
24

Aquí hay otra variación de la solución que devuelve verdadero si la cadena se puede convertir a un DateTimetipo y falso en caso contrario.

public static bool IsDateTime(string txtDate)
{
    DateTime tempDate;
    return DateTime.TryParse(txtDate, out tempDate);
}
Brendan Conrad
fuente
3
¡Bienvenido a StackOverflow! Mire las respuestas que ya se han proporcionado, especialmente cuando responde a una pregunta que tiene más de tres años y se ha respondido correctamente. Su respuesta ya ha sido cubierta por encuestados anteriores.
Bob Kaufman
3

Un problema con el uso DateTime.TryParsees que no admite el caso de uso de entrada de datos muy común de fechas ingresadas sin separadores, por ejemplo 011508.

Aquí hay un ejemplo de cómo apoyar esto. (Esto es de un marco que estoy construyendo, por lo que su firma es un poco extraña, pero la lógica central debería ser utilizable):

    private static readonly Regex ShortDate = new Regex(@"^\d{6}$");
    private static readonly Regex LongDate = new Regex(@"^\d{8}$");

    public object Parse(object value, out string message)
    {
        msg = null;
        string s = value.ToString().Trim();
        if (s.Trim() == "")
        {
            return null;
        }
        else
        {
            if (ShortDate.Match(s).Success)
            {
                s = s.Substring(0, 2) + "/" + s.Substring(2, 2) + "/" + s.Substring(4, 2);
            }
            if (LongDate.Match(s).Success)
            {
                s = s.Substring(0, 2) + "/" + s.Substring(2, 2) + "/" + s.Substring(4, 4);
            }
            DateTime d = DateTime.MinValue;
            if (DateTime.TryParse(s, out d))
            {
                return d;
            }
            else
            {
                message = String.Format("\"{0}\" is not a valid date.", s);
                return null;
            }
        }

    }
Robert Rossney
fuente
No me preocupan los separadores en mi caso porque estoy usando un cuadro de texto enmascarado, pero puedo ver lo útil que sería en otras situaciones que pueda encontrar con esta aplicación.
Matt
¿Cuál es la razón para usar la cadena DateTime sin separadores?
Sergei Kovalenko
1
    protected bool ValidateBirthday(String date)
    {
        DateTime Temp;

        if (DateTime.TryParse(date, out Temp) == true &&
      Temp.Hour == 0 &&
      Temp.Minute == 0 &&
      Temp.Second == 0 &&
      Temp.Millisecond == 0 &&
      Temp > DateTime.MinValue)
            return true;
        else
            return false;
    }

// Supongamos que la cadena de entrada tiene un formato de fecha corto.
por ejemplo, "2013/7/5" devuelve verdadero o
"2013/2/31" devuelve falso.
http://forums.asp.net/t/1250332.aspx/1
// bool booleanValue = ValidateBirthday ("12:55"); devuelve falso

Chung_TheWebDeveloper
fuente
1
private void btnEnter_Click(object sender, EventArgs e)
{
    maskedTextBox1.Mask = "00/00/0000";
    maskedTextBox1.ValidatingType = typeof(System.DateTime);
    //if (!IsValidDOB(maskedTextBox1.Text)) 
    if (!ValidateBirthday(maskedTextBox1.Text))
        MessageBox.Show(" Not Valid");
    else
        MessageBox.Show("Valid");
}
// check date format dd/mm/yyyy. but not if year < 1 or > 2013.
public static bool IsValidDOB(string dob)
{ 
    DateTime temp;
    if (DateTime.TryParse(dob, out temp))
        return (true);
    else 
        return (false);
}
// checks date format dd/mm/yyyy and year > 1900!.
protected bool ValidateBirthday(String date)
{
    DateTime Temp;
    if (DateTime.TryParse(date, out Temp) == true &&
        Temp.Year > 1900 &&
       // Temp.Hour == 0 && Temp.Minute == 0 &&
        //Temp.Second == 0 && Temp.Millisecond == 0 &&
        Temp > DateTime.MinValue)
        return (true);
    else
        return (false);
}
Julius
fuente
1

Todas las respuestas son bastante buenas, pero si desea utilizar una sola función, esto puede funcionar.

private bool validateTime(string dateInString)
{
    DateTime temp;
    if (DateTime.TryParse(dateInString, out temp))
    {
       return true;
    }
    return false;
}
Sayed Muhammad Idrees
fuente
1
¿Qué tal devolver el resultado de DateTime.TryParse () en lugar del bloque "if"? Además, su IDE se quejaría de la temperatura nunca utilizada, que podría declarar dentro de la llamada de función directamente como "out DateTime temp".
Sergei Kovalenko
0

También puede definir el DateTimeformato para unCultureInfo

public static bool IsDateTime(string tempDate)
{
    DateTime fromDateValue;
    var formats = new[] { "MM/dd/yyyy", "dd/MM/yyyy h:mm:ss", "MM/dd/yyyy hh:mm tt", "yyyy'-'MM'-'dd'T'HH':'mm':'ss" };
    return DateTime.TryParseExact(tempDate, formats, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out fromDateValue);
}
Yanga
fuente
-1
protected static bool CheckDate(DateTime date)
{
    if(new DateTime() == date)      
        return false;       
    else        
        return true;        
} 
Hasan_H
fuente
2
Si bien este código puede resolver la pregunta, incluir una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación y probablemente resultaría en más votos a favor. Recuerde que está respondiendo la pregunta a los lectores en el futuro, no solo a la persona que pregunta ahora. Por favor, editar su respuesta para agregar explicaciones y dar una indicación de lo que se aplican limitaciones y supuestos.
Brian
La pregunta es cómo validar un valor stringque podría contener o no un DateTImevalor. Está comprobando si un determinado DateTimetiene valores predeterminados (correspondientes a 0001-01-01T00:00:00.0000000). ¿Cómo responde esto a la pregunta?
dbc
-3
DateTime temp;
try
{
    temp = Convert.ToDateTime(grd.Rows[e.RowIndex].Cells["dateg"].Value);
    grd.Rows[e.RowIndex].Cells["dateg"].Value = temp.ToString("yyyy/MM/dd");
}
catch 
{   
    MessageBox.Show("Sorry The date not valid", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop,MessageBoxDefaultButton.Button1,MessageBoxOptions .RightAlign);
    grd.Rows[e.RowIndex].Cells["dateg"].Value = null;
}
Ashraf Khalifah
fuente
1
Tienes que comprobar que es válido por prueba. Entonces, puede usar try catch para verificar todos los tipos de variables y hacer funciones globales válidas y controlar todo en su proyecto. Saludos cordiales ... Ashraf
Khalifah
-3
DateTime temp;
try
{
    temp = Convert.ToDateTime(date);
    date = temp.ToString("yyyy/MM/dd");
}
catch 
{
    MessageBox.Show("Sorry The date not valid", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop,MessageBoxDefaultButton.Button1,MessageBoxOptions .RightAlign);
    date = null;
}
Ashraf Khalifah
fuente