Ben Fidge
Ben Fidge

Reputation: 203

Parse very long date format to DateTime in C#

How would I parse the following string date to a DateTime object in C#:

"Thursday, 1st January 1970"

This is coming from an XML feed and DateTime.Parse doesnt seem to like it in en-GB locale. The feed will only ever come from a british server so I'm not to worried about globalization issues

My initial brute force approach would be to:

Im sure there must be a far more elegant way though? I couldnt get DateTime.Prse or Datetime.ParseExact to work

Upvotes: 2

Views: 2486

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1503140

I don't believe that DateTime parsing knows anything about ordinals, but it should be able to handle everything else. So you could use:

public static string RemoveOrdinals(string input)
{
    // Ugly but oh so simple.
    return input.Replace("0th", "0")
                .Replace("1st", "1")
                .Replace("2nd", "2")
                .Replace("3rd", "3")
                .Replace("11th", "11") // Need to handle these separately...
                .Replace("12th", "12")
                .Replace("13th", "13")
                .Replace("4th", "4")
                .Replace("5th", "5")
                .Replace("6th", "6")
                .Replace("7th", "7")
                .Replace("8th", "8")
                .Replace("9th", "9");
}

Then:

string text = RemoveOrdinals(text);
DateTime date = DateTime.ParseExact(text, "dddd, d MMMM yyyy",
                                    CultureInfo.GetCulture("en-GB"));

(As a quick plug, of course you want just a date rather than a date/time. Unfortunately .NET doesn't have a type to represent that - but you could use LocalDate in my Noda Time library. We don't handle ordinals either - yet, anyway - so you'd still need the extra method. Let me know if you'd like to see the relevant code though.)

Upvotes: 6

RJ Lohan
RJ Lohan

Reputation: 6527

Just to provide a slightly different take on this, and give you an idea of some other options you have; you can specify the format to DateTime.Parse (or TryParse as in my example) to account for circumstances like this, without trying to 'pre format' the string into something else with String.Replace calls and the like;

public DateTime ParseOrdinalDateTime(string dt)
{
    string[] expectedFormats = 

    DateTime d;
    if (DateTime.TryParseExact(dt, "dddd, d\"st\" MMMM yyyy", null, DateTimeStyles.None, out d))
        return d;
    if (DateTime.TryParseExact(dt, "dddd, d\"nd\" MMMM yyyy", null, DateTimeStyles.None, out d))
        return d;
    if (DateTime.TryParseExact(dt, "dddd, d\"rd\" MMMM yyyy", null, DateTimeStyles.None, out d))
        return d;
    if (DateTime.TryParseExact(dt, "dddd, d\"th\" MMMM yyyy", null, DateTimeStyles.None, out d))
        return d;

    throw new InvalidOperationException("Not a valid DateTime string");
}

The reason I'd propose this approach is that it sets out your input expectations very clearly, and contains the behaviour to a single method. If the format changes, you can just specify a different format string in here and account for a new date time string structure.

Or, a slight variation on the above, taking into account below comments;

private static DateTime ParseOrdinalDateTime(string dt)
{
    string[] expectedFormats = new[]
    {
        "dddd, d'st' MMMM yyyy",
        "dddd, d'nd' MMMM yyyy",
        "dddd, d'rd' MMMM yyyy",
        "dddd, d'th' MMMM yyyy"
    };

    try
    {
        return DateTime.ParseExact(dt, expectedFormats, null, DateTimeStyles.None);
    }
    catch (Exception e)
    {
        throw new InvalidOperationException("Not a valid DateTime string", e);
    }
}

NOTE: The only reason I catch and throw an InvalidOperationException above is to protect the caller from having to catch Exception to handle whatever possible exceptions DateTime.ParseExact may throw. You could easily modify this API.

Upvotes: 5

Haney
Haney

Reputation: 34912

Use DateTime.Parse with a culture specific formatter:

http://msdn.microsoft.com/en-us/library/kc8s65zs.aspx

First reverse the logic at this answer to strip the "st", "nd" etc. from the day of the month:

https://stackoverflow.com/a/4544313/2420979

Then just use DateTime.Parse normally:

var result = DateTime.Parse("Thursday, 1 January 1970", new CultureInfo("en-GB"));

Upvotes: 0

Related Questions