1

I have the following method and it works correctly as far as handling a real invalid/valid date, however, if I encounter an empty string or a date with a mask such as __/__/____, I want to pass those as valid, but DateTime.TryParse invalidates them. How can I modify the method below to pass my Invalid scenarios? Below the following method is an example program:

public bool ValidateDate(string date, out string message)
{
    bool success = true;
    message = string.Empty;
    DateTime dateTime;

    if(DateTime.TryParse(date,out dateTime))
    {
        success = false;
        message = "Date is Invalid";
    }

    return success;
}

void Main()
{
    //The only date below that should return false is date4.

    string date = "01/01/2020";
    string date2 = "";
    string date3 = "__/__/____";
    string date4 = "44/__/2013";

    string message;

    ValidateDate(date, out message); //Should return true
    ValidateDate(date2, out message); //Should return true
    ValidateDate(date3, out message); //Should return true
    ValidateDate(date4, out message); //Should return false
}

I can't change it to if(!DateTime.TryParse(date3,out dateTime)) because this will then return false for the dates I want validated.

I also tried doing something like if(!date3.contains("_") && DateTime.TryParse(date3,out dateTime)), but this still fails. Should I flip the order of my validation? The problem is that I am not just returning false on the first invalid date, I am building a StringBuilder of all the invalid dates and then returning that, so I didn't think:

if(DateTime.TryParse(date3,out dateTime))
        return true;
    else
        return true;

public bool ValidateDate(string date, out string message)
{
    string[] overrides = {"","__/__/____"};

    bool success = true;
    message = string.Empty;
    DateTime dateTime;

    if(!overrides.Contains(date) && !DateTime.TryParse(date,out dateTime))
    {
        success = false;
        message = "Date is Invalid";
    }


    return success;
}
Xaisoft
  • 45,655
  • 87
  • 279
  • 432

2 Answers2

4

Can you just look at an array of overrides before running through the DateTime.TryParse method?

static string[] overrides = { "", "__/__/____" };
public bool ValidateDate(string date, out string message)
{
    bool success = true;
    message = string.Empty;

    if(overrides.Contains(date)) { return success; }

    DateTime dateTime;

    if(!DateTime.TryParse(date,out dateTime))
    {
        success = false;
        message = "Date is Invalid";
    }


    return success;
}
Joseph Yaduvanshi
  • 20,241
  • 5
  • 61
  • 69
1

There are lots of ways to skin this cat. I guess it depends on how much invalid data you want to treat as valid. Also, DateTime.TryParse will take into account the current culture settings, so maybe you should too?

bool ValidateDate(string date, out string message)
{
    message = string.Empty;

    if (date == null)
        return true;

    const string mask = "_";
    var separator = CultureInfo.CurrentCulture.DateTimeFormat.DateSeparator;
    var test = date.Replace(mask, string.Empty).Replace(separator, string.Empty);
    if (string.IsNullOrWhiteSpace(test))
        return true;

    DateTime dateTime;
    if (!DateTime.TryParse(date, out dateTime))
    {
        message = "Date is Invalid";
        return false;
    }

    return true;
}

I suppose you could do it with a regular expression also. There are lots of valid solutions.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Can you elaborate a bit more on culture? My dates will be stored with `en-US` culture regardless of culture? – Xaisoft Jun 20 '13 at 03:35
  • 2
    Stored as `DateTime`, culture doesn't matter. But as strings, they do. How do you know the user will enter mm/dd/yyyy or dd/mm/yyyy? And are you sure the separator will always be a forward slash, or might it be a dash or period? What if the year comes first? If you are going to be culture aware, then you have to account for these things. If you're going to lock in to a specific culture, then you should probably use `TryParseExact` and pass the format and culture in. – Matt Johnson-Pint Jun 20 '13 at 05:00