26

Is there any way to validate datetime field before inserting it into appropriate table?

Trying to insert with try/catch block is not a way.

Thanks,

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MichaelVerossa
  • 439
  • 1
  • 7
  • 11
  • How are you inserting the data? ALso, what type of validation are you talking about? Within a certain range or that its a valid format? – iamkrillin Aug 14 '11 at 03:25

8 Answers8

39

Not sure if I'm being overly pedantic there, but DateTime.TryParse will validate whether a value is a valid DateTime object. OP asked about verifying a value before inserting into SQL Server datetime. The range of acceptable values for a SQL Server datetime is "January 1, 1753, through December 31, 9999" That does not hold true for DateTime .NET objects. This script assigns a value of "1/1/0001 12:00:00 AM" to badDateTime and it successfully parses.

DateTime d = DateTime.MinValue;
string badDateTime = DateTime.MinValue.ToString();
Console.WriteLine(badDateTime);
DateTime.TryParse(badDateTime, out d);

However, if you attempted to store that into a datetime field, it would fail with "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value."

A commenter asked why I used 997 for milliseconds, this is covered under SQL Server 2008 and milliseconds but saving you a click, 997 is the largest value you can store in a datetime datatype. 998 will be rounded up to 1 second with 000 milliseconds

    /// <summary>
    /// An initial pass at a method to verify whether a value is 
    /// kosher for SQL Server datetime
    /// </summary>
    /// <param name="someval">A date string that may parse</param>
    /// <returns>true if the parameter is valid for SQL Sever datetime</returns>
    static bool IsValidSqlDatetime(string someval)
    {
        bool valid = false;
        DateTime testDate = DateTime.MinValue;
        DateTime minDateTime = DateTime.MaxValue;
        DateTime maxDateTime = DateTime.MinValue;

        minDateTime = new DateTime(1753, 1, 1);
        maxDateTime = new DateTime(9999, 12, 31, 23, 59, 59, 997);

        if (DateTime.TryParse(someval, out testDate))
        {
            if (testDate >= minDateTime && testDate <= maxDateTime)
            {
                valid = true;
            }
        }

        return valid;
    }

This is probably a better approach as this will attempt to cast the DateTime object into an actual sql datetime data type


    /// <summary>
    /// An better method to verify whether a value is 
    /// kosher for SQL Server datetime. This uses the native library
    /// for checking range values
    /// </summary>
    /// <param name="someval">A date string that may parse</param>
    /// <returns>true if the parameter is valid for SQL Sever datetime</returns>
    static bool IsValidSqlDateTimeNative(string someval)
    {
        bool valid = false;
        DateTime testDate = DateTime.MinValue;
        System.Data.SqlTypes.SqlDateTime sdt;
        if (DateTime.TryParse(someval, out testDate))
        {
            try
            {
                // take advantage of the native conversion
                sdt = new System.Data.SqlTypes.SqlDateTime(testDate);
                valid = true;
            }
            catch (System.Data.SqlTypes.SqlTypeException ex)
            {

                // no need to do anything, this is the expected out of range error
            }
        }

        return valid;
    }
Community
  • 1
  • 1
billinkc
  • 59,250
  • 9
  • 102
  • 159
  • Yes, you're right. I'm looking for a solution to make sure the string I have as DateTime now will be insterted into Datetime field in table without any error. – MichaelVerossa Aug 14 '11 at 04:03
  • Edited to add a simple method that will check the values are in range. Going to try a second approach, might be less error prone – billinkc Aug 14 '11 at 04:12
  • I'll try your method! Thank you, billinkc! – MichaelVerossa Aug 14 '11 at 04:33
  • Using the SqlDateTime will not work all the time. If a user inputs 10/17 without a year, the method above adds it for validation. But when 10/17 gets to the table in sql server, it throws an error. – Zath Oct 16 '14 at 13:17
  • Any particular reason for using 997 milliseconds, rather than 999 when defining maxDateTime? – graphicdivine Nov 02 '15 at 10:29
  • Nevermind, I found this - http://stackoverflow.com/questions/8153963/sql-server-2008-and-milliseconds – graphicdivine Nov 02 '15 at 10:41
  • Good answer. Would be nice if there was a .Net built-in SqlDateTime.TryParse() so you don't need to catch an Exception. – Mike W Mar 01 '18 at 16:17
  • Nothing wrong with the code above, but I like to looking at it more linear like if (minDateTime <= testDate && testDate <= maxDateTime) – Deszolate_C Apr 16 '20 at 06:57
24

Try this without hardcoding sql dateTime value:

public bool IsValidSqlDateTime(DateTime? dateTime)
{
    if (dateTime == null) return true;
    
    DateTime minValue = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
    DateTime maxValue = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;

    if (minValue > dateTime.Value || maxValue < dateTime.Value)
        return false;

    return true;
}
Ankush Madankar
  • 3,689
  • 4
  • 40
  • 74
  • 5
    You could also use the explicit casting operator defined on the SqlDateTime structure; instead of parsing the string representation: `var minValue = (DateTime) System.Data.SqlTypes.SqlDateTime.MinValue;` – Styxxy Jul 06 '15 at 14:11
  • @Styxxy Thank you for the suggestion! Answer is updated now. – Ankush Madankar May 15 '20 at 04:10
2

This is another take on billinkc's answer. However, in this method the .Value property of the min/max is used to avoid parsing and try/catch. Someone mentioned they wanted to ensure they are inserting a valid date into SQL Server. So, I took the approach of returning a date that is valid for SQL Server. This could easily be changed to a boolean method that checks to see if the dateToVerify is a valid SQL Server date.

protected DateTime EnsureValidDatabaseDate(DateTime dateToVerify)
{
    if (dateToVerify < System.Data.SqlTypes.SqlDateTime.MinValue.**Value**)
    {
        return System.Data.SqlTypes.SqlDateTime.MinValue.Value;
    }
    else if (dateToVerify > System.Data.SqlTypes.SqlDateTime.MaxValue.**Value**)
    {
        return System.Data.SqlTypes.SqlDateTime.MaxValue.Value;
    }
    else
    {
        return dateToVerify;
    }
}
2
<asp:RangeValidator runat="server" ID="rgvalDate" ControlToValidate="txtDate" Text="[Invalid]" Type="Date" MinimumValue="1/1/1753" MaximumValue="12/31/9999" />

OR

custom validator:

    protected void cvalDOB_ServerValidate(object sender, ServerValidateEventArgs e)
    {
        e.IsValid = IsValidSqlDateTime(e.Value);
    }

    public static bool IsValidSqlDateTime(object Date)
    {
        try
        {
            System.Data.SqlTypes.SqlDateTime.Parse(Date.ToString());
            return true;
        }
        catch
        {
            return false;
        }
    }
Bolo
  • 1,494
  • 1
  • 19
  • 19
2

Here is a class with an extension method to allow a check such as if(myDateTime.IsValidSqlDateTime()) { ... }:

public static class DateTimeExtensionMethods
{
    public static bool IsValidSqlDateTime(this DateTime dateTime)
    {
        return !(dateTime < (DateTime) SqlDateTime.MinValue ||
                 dateTime > (DateTime) SqlDateTime.MaxValue);
    }
}
Chris Peacock
  • 4,107
  • 3
  • 26
  • 24
1

Could you provide a bt more information on where the datetime value is coming from; a web form? You could simply add a CompareValidator as follows

<asp:CompareValidator ID="CompareValidator1" runat="server" 
            ControlToValidate="txtDate" 
            Type="Date" 
            ErrorMessage="CompareValidator">
</asp:CompareValidator>
naveen
  • 53,448
  • 46
  • 161
  • 251
Obi
  • 3,091
  • 4
  • 34
  • 56
0

If you are mentioning about server side validation of your DateTime field, use DateTime.TryParse. A quick and dirty example will be

DateTime dateValue;
string dateString = "05/01/2009 14:57:32.8";
if (DateTime.TryParse(dateString, out dateValue))
{
    // valid date comes here.
    // use dateValue for this
}
else
{
    // valid date comes here
}
naveen
  • 53,448
  • 46
  • 161
  • 251
0

DateTime.TryParse is the best validator

DateTime temp;
if(DateTime.TryParse(txtDate.Text, out temp))
//Works
else
// Doesnt work
Vinay
  • 1,016
  • 8
  • 22
  • 1
    not in this case. Every SQLDatetime is a valid .NET datetime but not the other way around. – bjoern Mar 07 '13 at 19:43