astralmaster
astralmaster

Reputation: 2465

Parsing string input C#

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?

Upvotes: 2

Views: 192

Answers (5)

Eric
Eric

Reputation: 5743

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);

Upvotes: 3

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131581

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)

Upvotes: 1

Rahul Nikate
Rahul Nikate

Reputation: 6337

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

Upvotes: 1

Winky2222
Winky2222

Reputation: 46

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.

Upvotes: -1

Tushar Gupta
Tushar Gupta

Reputation: 15923

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.

Upvotes: 2

Related Questions