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?
CodePudding user response:
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 theprovider
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".