-3

We have an integration partner who insists on sending us datetimes as strings in the format yyyyMMdd:Hmm, e.g., "20211029:102". Note that the hour does not have a leading zero.

I tried to parse it like this:

Datetime datetime = DateTime.ParseExact(
   "20211029:102", 
   "yyyyMMdd:hmm", 
   CultureInfo.InvariantCulture, 
   DateTimeStyles.None
);

But this results in

FormatException••• String '20211029:102' was not recognized as a valid DateTime.

I can make it work by re-adding the missing zero, something like:

string datetimeParts = "20211029:102".Split(":");
string value = datetimeParts[0] + datetimeParts[1].PadLeft(4, '0');
Datetime dt = DateTime.ParseExact(
    value, 
    "yyyyMMddHHmm", 
    CultureInfo.InvariantCulture, 
    DateTimeStyles.None
);

But I feel I shouldn't need to "preparse" the value. Is it possible to parse this format without pre-processing?

J...
  • 30,968
  • 6
  • 66
  • 143
Brian Kessler
  • 2,187
  • 6
  • 28
  • 58

1 Answers1

4

The problem lies in the time part of your format string, so my answer will explain why you cannot parse 102 with the format string Hmm. (I know you wrote hmm, but since you don't have an AM/PM designator, I'll assume that you meant to write Hmm instead. The same reasoning applies to hmm.)

If we look at the the reference source, we can see that the DateTime parser is "greedy": If the parser encounters a single-letter format specifier (such as H), it will still try to consume 2 digits, if two digits are available.

In your case, two digits are available, so H will consume 10 of 102. This only leaves 2 for the minute, which won't match mm (since it only has one digit).

Given this limitation, it's not possible to parse a DateTime value formatted as Hmm with DateTime.ParseExact. The documentation notes the following:

Note

If format is a custom format pattern that does not include date or time separators (such as "yyyyMMddHHmm"), use the invariant culture for the provider parameter and the widest form of each custom format specifier. For example, if you want to specify hours in the format pattern, specify the wider form, "HH", instead of the narrower form, "H".

Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • Cheers for the great answer on why "yyyyMMdd:Hmm" and "yyyyMMdd:hmm" can't work. :-) So that only leaves the question whether there are any alternatives to Datetime.ParseExact which could accept the "H"? But given the gist of the feedback, it seems doubtful anyone would want to.... – Brian Kessler Oct 05 '21 at 10:50
  • 1
    @BrianKessler: I doubt that there is an alternative, and since you have a readable, working solution, I doubt that putting further effort into finding an alternative is worthwhile. – Heinzi Oct 05 '21 at 11:29
  • 1
    @BrianKessler: As a side note: Regular expressions *do* support backtracking, so something like `(?[0-9]?[0-9])(?[0-9][0-9])` should work. But that won't be shorter than your current solution either. – Heinzi Oct 06 '21 at 07:13