Parsing very long DateTime format in C #
How would I parse the following string date for a DateTime object in C #:
"Thursday 1st January 1970"
It comes from XML feed and DateTime.Parse doesn't seem to like the en-GB locale. The feed will only ever be from a UK server, so I won't worry about globalization issues.
My initial brute force approach:
- Remove everything before the comma and include it, and the trailing space will leave "Jan 1, 1970".
- Then remove "st", "nd", "rd" or "th" to leave "January 1st 1970"
- Then convert the month to its numeric equivalent, leaving "1 1 1970"
- Then replace spaces with "/" to get "1/1/1970"
I'm sure there must be a much more elegant way? I couldn't get DateTime.Prse or Datetime.ParseExact to work
source to share
Just to give it a little thought and give you an idea of ββsome of the other options you have; you can specify the DateTime.Parse format (or TryParse as in my example) to accommodate such circumstances without trying to "preformat" the string to something else using calls String.Replace
or 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 suggest this approach is because it spells out your input expectations very clearly and contains behavior for a single method. If the format changes, you can simply specify a different format string here and create a new date string string.
Or a slight variation of the above, taking into account the following 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 will catch and throw the InvalidOperationException above is to protect the caller from catch Exception
handling any possible exceptions DateTime.ParseExact
. You can easily change this API.
source to share
I don't believe that parsing DateTime
knows nothing about ordinals, but it should be able to handle everything else. Thus, you can 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 plugin, of course you only want date and not date / time. Unfortunately .NET doesn't have this type to represent this, but you could use Noda TimeLocalDate
in my library . We don't handle ordinals either - that's all is equal anyway, so you need an extra method. Let me know if you want to see the relevant code though.)
source to share
Use DateTime.Parse
with a culture specific format:
http://msdn.microsoft.com/en-us/library/kc8s65zs.aspx
The first reverse logic in this answer is to remove "st", "nd", etc. from the day of the month:
fooobar.com/questions/366361 / ...
Then just use DateTime.Parse
generally:
var result = DateTime.Parse("Thursday, 1 January 1970", new CultureInfo("en-GB"));
source to share