0

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?

Cybercop
  • 8,475
  • 21
  • 75
  • 135
  • Why didn't the question you linked to help? What was wrong/missing with the existing answer? – Enigmativity Feb 04 '18 at 10:29
  • 1
    Also, what does the`-60` after the `UTC` represent? – Enigmativity Feb 04 '18 at 10:30
  • `-60` is _not_ a valid UTC Offset value if you consider it as such. – Soner Gönül Feb 04 '18 at 10:31
  • As you can see in the accepted answer, adding Z in the end helped the person who asked the question, also other answers that suggested adding UTC did not help for my case. As you can see I have tried parsing as per the answers provided there but I get same error "string was not recognized as a valid date time" – Cybercop Feb 04 '18 at 10:34
  • @SonerGönül yes it looks weird to me as well, but the system I am using gives me that date which I have to parse to c# datetime object. Any suggestions? – Cybercop Feb 04 '18 at 10:35
  • Do you know which timezone these dates are coming in?Are they always -60 minutes offset? – DavidG Feb 04 '18 at 10:36
  • @Cybercop Your bigger problem seems as [Garbage in, garbage out](https://en.wikipedia.org/wiki/Garbage_in,_garbage_out), not parsing. Have you try to clean your `-60` part before parsing? It seems unnecessary to me. – Soner Gönül Feb 04 '18 at 10:37
  • @Cybercop - It's really just a matter of trying to work through the string formats carefully. Did you try `DateTime.ParseExact(dateToParse, "dd.MM.yyyy HH:mm:ss.fff UTC-60", CultureInfo.InvariantCulture)`? – Enigmativity Feb 04 '18 at 10:37
  • @DavidG `+-[mm]` is not a valid UTC Offset. It can be only -60 hours which doesn't exists. I think that value is not offset _at all_. – Soner Gönül Feb 04 '18 at 10:39
  • @SonerGönül I know but it's clearly not going to be 60 hours is it? I'm just trying to come up with a workaround. – DavidG Feb 04 '18 at 10:40
  • @Enigmativity I tried what you said but same error. There must be some clever way which I am missing. – Cybercop Feb 04 '18 at 10:40
  • The only problem seems to be UTC-60, which I do confess is bizzare. Also, is fff right string for milliseconds? – Cybercop Feb 04 '18 at 10:41
  • @Cybercop The code from Enig should work fine, are you sure you tried it exactly as is? – DavidG Feb 04 '18 at 10:43
  • @Cybercop Start by figuring out what is the meaning of the offset `-60` at the end of the string. This could be an abbreviated way of writing -6:00 or -1.00 (i.e. interpreting 60 as a number of minutes). Both guesses are equally valid, so you need to get solid information on what this actually represents. – Sergey Kalinichenko Feb 04 '18 at 10:44
  • @Cybercop - The suggestion I gave you worked when I tested it. – Enigmativity Feb 04 '18 at 10:51
  • @Enigmativity Sorry, what you said works I was using hh instead of HH – Cybercop Feb 04 '18 at 10:53
  • 1
    @Cybercop - That was part of my point about being careful with the format strings. – Enigmativity Feb 04 '18 at 10:57

2 Answers2

3

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.

Natan
  • 4,686
  • 5
  • 30
  • 48
0

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;
Chris Schaller
  • 13,704
  • 3
  • 43
  • 81