2

Let's say I have a string that is bound to console input and must contain date data in any of the following formats:

"dd/mm/yyyy"
"dd.mm.yyyy"
"dd,mm,yyyy"

What is the safest way to parse this string into DateTime object? Should I use Regex approach or simply iterate through String.Format() method with all possible upper mentioned input formats till it succeeds in parsing?

3
  • 1
    Do you know what cultures correspond to these values? If you do, you can pass them to any parsing function Commented Apr 23, 2015 at 9:53
  • It isn't actually based on cultural context, I have to parse real user input and different people tend to type date differently even though they have read the manual and know the format the software expects. I just don't want to throw an exception and make them type the date again but rather parse it regardless of those differences Commented Apr 23, 2015 at 9:57
  • You may want to add - then. I see from Wikipedia that it's used as a separator in Germany, France Commented Apr 23, 2015 at 10:26

5 Answers 5

3

DateTime.ParseExact do have an overload that you can supply multiple format to it

Converts the specified string representation of a date and time to its DateTime equivalent using the specified array of formats, culture-specific format information, and style. The format of the string representation must match at least one of the specified formats exactly or an exception is thrown.

Pass CultureInfo.InvariantCulture to IFormatProvider should handle the separator correctly for . , /

var dateformats = new[] { "dd/mm/yyyy", "dd.mm.yyyy", "dd,mm,yyyy" };

DateTime.ParseExact("23/04/2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None);
DateTime.ParseExact("23.04.2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None);
DateTime.ParseExact("23,04,2015", dateformats, CultureInfo.InvariantCulture, DateTimeStyles.None);
Sign up to request clarification or add additional context in comments.

7 Comments

DateTime.TryParseExact is a better option in this case as it doesn't throw if it fails. The real problem is that there is only one format but the date separator changes. The OP will have to pass a custom CultureInfo for each try
@PanagiotisKanavos You are right but OP mentioned .. must contain date data in any of the following formats, then TryParseExact() added nothing to this case.
On the contrary. You can check each different format (actually, separator) to see which returns true. It's not only safer but much faster than catching exceptions for each failed format
First, this edit will throw at least one exception. Second, the first line will fail if the user's culture uses a separator other than /. / is a special character, replaced by the current culture's date separator
@PanagiotisKanavos Just curious, what actually the use of IFormatProvider if it still fail when InvariantCulture supplied?
|
2

You need to use DateTime.TryParseExact as there are multiple formats it wont generate any exceptions

Converts the specified string representation of a date and time to its DateTime equivalent. The format of the string representation must match a specified format exactly. The method returns a value that indicates whether the conversion succeeded.

7 Comments

This deals with the issue in the safest way as far as I can tell.
Yes @astralmaster as as it doesn't throw any exception if it fails.
Not quite. / is the date separator symbol, replaced by the actual separator from the user's culture. Parsing of dd/mm/yyyy will fail if that separator is . or ,.
@PanagiotisKanavos yes that's why the OP need the TryParseExact as exception will not be thrown
@TusharGupta Although the Idea is for the solution to be able to parse the input regardless of user's culture
|
1

It's not enough to use DateTime.ParseExact or DateTime.TryParseExact. The / is a special formatting character, the date separator character. In a format string it will be replaced with whatever the date separator is for the application's current culture. It can't be escaped because it is not a special character like \. This will cause problems if your system's culture uses . (Russia and other countries).

To specify a different date separator you need to create a CultureInfo object with the separator you want. The following function accepts a list of separators and tries to parse dates using each separator until one of them succeeds:

public static bool TryParseDate(string input, string[] separators, out DateTime date)
{
    var ci = (CultureInfo) CultureInfo.InvariantCulture.Clone();

    foreach (var separator in separators)
    {
        ci.DateTimeFormat.DateSeparator = separator;
        DateTime result;
        if (DateTime.TryParseExact(input, "dd/MM/yyyy", ci, DateTimeStyles.None, 
                                   out date))
            return true;
    }
    date=new DateTime();
    return false;
}

There's no need to define multiple formats because dd/MM/yyyy matches all cases.

This allows you to write code like the following snippet:

var separators = new []{"/",".",",","-"};
DateTime result;
var success1 = TryParseDate("12.05.2015", separators, out result);
var success2 = TryParseDate("12/05/2015", separators, out result);
var success3 = TryParseDate("12,05,2015", separators, out result);
var success4 = TryParseDate("12-05-2015", separators, out result);

I added - because I see it's a common separator in Germany. You can make the function even more generic by passing the format as another parameter.

TryParseExact accepts multiple format parameters. If it weren't for the / separator, you could write a single call with all formats:

var formats=new []{"dd.MM.yyyy","dd,MM,yyyy","dd-MM-yyyy"};
DateTime result;
var success=DateTime.TryParseExact(input, formats, 
                       CultureInfo.InvariantCulture, DateTimeStyles.None, 
                       out date)

Comments

1

DateTime.ParseExact Method

Converts the specified string representation of a date and time to its DateTime equivalent.

Or

DateTime.TryParseExact Method

Converts the specified string representation of a date and time to its DateTime equivalent. The format of the string representation must match a specified format exactly. The method returns a value that indicates whether the conversion succeeded.

Note :

Parse takes regional settings (culture of current thread) into account. Therefore, you need to specify the correct format explicitly with an invariant culture eg. en-US

Comments

-1

I reckon just iterate through String.Format, it is probably easier than using a regex. But if you have actual users inputing into wherever you got the DateTimes, a regex is safer, but it should still be surrounded by a try to make it crash-proof.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.