Cybercop
Cybercop

Reputation: 8678

C# Datetime.ParseExact for a parsing a string containing UTC text

I have a date time string that looks like this:

13.08.2014 17:17:45.000 UTC-60

I am trying to parse it into a C# date time object but it is not working as I expected.

Here is what I tried:

DateTime.ParseExact(dateToParse, "dd.MM.yyyy hh:mm:ss.fff Z", CultureInfo.InvariantCulture);

DateTime.ParseExact(dateToParse, "dd.MM.yyyy hh:mm:ss.fff UTC", CultureInfo.InvariantCulture);

DateTime.ParseExact(checkInDate, "dd.MM.yyyy hh:mm:ss.fff", CultureInfo.InvariantCulture);

They all return same error

{"String was not recognized as a valid DateTime."}

Some of the existing questions like this did not help either.

Any suggestions?

Upvotes: 0

Views: 1358

Answers (2)

Chris Schaller
Chris Schaller

Reputation: 16554

How much control do you have over the time format. .Net datetime parsing expects 2 things that are wrong with the current time format that you are trying to parse:

First, you have 24 hour time, so in your format you must use HH for hours, the lower case hh implies that the hours will be 12 hour format.

The UTC issue is another one that will require you to modify the string first, .Net expects timezone information in the form of HH:mm, so the following string and conversion will work, notice the key differences

var dateToParse = "13.08.2014 17:17:45.000 -01:00";
var value = DateTimeOffset.ParseExact(dateToParse, "dd.MM.yyyy HH:mm:ss.fff zzz", CultureInfo.InvariantCulture);
  1. Use DateTimeOffset to maintain the TimeZone information
  2. HH to map the hours
  3. zzz to map the timezone information

So, to address you question, how can we parse the string into a format that we can then use to parse into a date time:

dateToParse = "13.08.2014 17:17:45.000 UTC-60";
string utc = null;
if (dateToParse.Contains("UTC"))
{
    var tokens = dateToParse.Split(new string[] { "UTC" }, StringSplitOptions.None);
    dateToParse = tokens[0];
    utc = tokens[1];

    int minutes = int.Parse(utc);
    var offset = TimeSpan.FromMinutes(minutes);
    bool negative = offset.Hours < 0;
    dateToParse += (negative ? "-" : "") + Math.Abs(offset.Hours).ToString().PadLeft(2,'0') + ":" + offset.Minutes.ToString().PadLeft(2,'0');
}
var value = DateTimeOffset.ParseExact(dateToParse, "dd.MM.yyyy HH:mm:ss.fff zzz", CultureInfo.InvariantCulture);

To be honest, that was more complicated than I thought, there might be some regex expressions that might help, but this first principals approach to manipulating the string first works with your string.

Finally, now that we have a DateTimeOffset value, you can easily convert this into any local or other timezone without too much hassel, if you need to:

var asUtc = dateValue.UtcDateTime;
var asLocal = dateValue.LocalDateTime;
var asSpecific = dateValue.ToOffset(TimeSpan.FromHours(10)).DateTime;

Upvotes: 0

Natan
Natan

Reputation: 4958

First, your main problem there with parsing is that your're using hh for 24h format. That should be HH. This should work:

DateTime.ParseExact("13.08.2014 17:17:45.000", "dd.MM.yyyy HH:mm:ss.fff", null, System.Globalization.DateTimeStyles.AssumeUniversal)

As for the UTC part, that's not standard format, so I suggest you to create a helper method that splits this string in 2, parse the first part as provided above, and parse the number after UTC and either add that to your DateTime:

myDate.AddMinutes(Int32.Parse("-60"))

Or create a DateTimeOffset. In either case, you must parse them individually.

Upvotes: 3

Related Questions