Sunday, March 6, 2011

Validate a DateTime in C#

I doubt I am the only one who has come up with this solution, but if you have a better one please post it here. I simply want to leave this question here so I and others can search it later.

I needed to tell whether a valid date had been entered into a text box and this is the code that I came up with. I fire this when focus leaves the text box.

try
{
    DateTime.Parse(startDateTextBox.Text);
}
catch
{
    startDateTextBox.Text = DateTime.Today.ToShortDateString();
}
From stackoverflow
  • DateTime.TryParse This I believe is faster and it means you dont have to use ugly try/catches :)

    e.g

    DateTime temp;
    if(DateTime.TryParse(startDateTextBox.Text, out temp))
    //yay
    else
    // :(
    
    Alex Fort : You beat me to it ;)
    qui : Fastest gun in the west ;)
  • I would use the DateTime.TryParse() method: http://msdn.microsoft.com/en-us/library/system.datetime.tryparse.aspx

  • Don't use exceptions for flow control. Use DateTime.TryParse and DateTime.TryParseExact. Personally I prefer TryParseExact with a specific format, but I guess there are times when TryParse is better. Example use based on your original code:

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

    Reasons for preferring this approach:

    • Clearer code (it says what it wants to do)
    • Better performance than catching and swallowing exceptions
    • This doesn't catch exceptions inappropriately - e.g. OutOfMemoryException, ThreadInterruptedException. (Your current code could be fixed to avoid this by just catching the relevant exception, but using TryParse would still be better.)
  • What about using TryParse?

  • A problem with using DateTime.TryParse is that it doesn't support the very common data-entry use case of dates entered without separators, e.g. 011508.

    Here's an example of how to support this. (This is from a framework I'm building, so its signature is a little weird, but the core logic should be usable):

        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;
                }
            }
    
        }
    
    Matt : I am not worried about seporators in my case because I am using a Masked Text Box, but I can see how that would be handy in other situations I may encounter with this app.

0 comments:

Post a Comment