2

I have tried like below:

DateTime.ParseExact("Feb520161000PM", 
"MMMdyyyyhhmmtt", CultureInfo.InvariantCulture)

But it's giving FormatException.

Interestingly

DateTime.ParseExact(DateTime.Now.ToString("MMMdyyyyhhmmtt"), "MMMdyyyyhhmmtt", 
CultureInfo.InvariantCulture)

This is also giving format exception.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Satyajit
  • 2,150
  • 2
  • 15
  • 28
  • First problem I see here is the day. How do you want to represent a day with two digits with just MMMdyyyy? – cap7 Feb 05 '16 at 20:05
  • By the way, your second code example will not throw exception after 10th day of a month since `d` will map perfectly two digit day number. – Soner Gönül Feb 07 '16 at 16:36
  • @SonerGönül, that's right but a solution should work for all day values. If it fails for any value then it's not a complete solution as per me – Satyajit Feb 08 '16 at 11:41
  • @Satyajit As we said, there is _no_ solution for all day values. You kinda _have to_ use custom method for only your case. I would suggest you to _not_ to get this kind of string at first as Alexei mentioned. – Soner Gönül Feb 08 '16 at 12:16

2 Answers2

4

The format is not parseable with regular parsing which work from left to right - you need custom code that parses value from right to left instead as you want leftmost number to be variable width ("Feb111111111PM").

If possible - change format to one with fixed width fields (preferably ISO8601). Otherwise split string manually and construct date from resulting parts (time part would work fine by itself, so just need to manually parse date part).

Some other approaches and info can be found in similar post about time - DateTime.ParseExact - how to parse single- and double-digit hours with same format string?

Community
  • 1
  • 1
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • When you say Leftmost number to be variable width, did you mean, the value could be `Feb5` and `Feb25` ? – Shyju Feb 05 '16 at 17:55
  • 1
    @Shyju yes - for "Feb1201510..." parsing had to decide whether it is "Feb 1, 2015" or "Feb 12, 0151" when scanning from left to right. ("Obviously I want Feb 1, 2015" can't yet be expressed to computers without writing code) – Alexei Levenkov Feb 05 '16 at 18:00
  • Thanks ! That explains it. I think you should add that to the answer for future readers. – Shyju Feb 05 '16 at 18:01
  • `Feb0520161000PM` and `MMMddyyyyhhmmtt` will work. Also `Feb-5-20161000PM` and `MMM-d-yyyyhhmmtt` – Shyju Feb 05 '16 at 18:02
  • wow, was looking for questions to answer and you just taught me something really cool about parsing dates, thanks @AlexeiLevenkov. Never have run into that right to left scenario before. – Kyle Bachmann Feb 05 '16 at 21:09
  • Thanks for your response. I have got the idea of right to left parsing. But does the R-L approach needed to be changed(considired) as per cases or right to left will work or suitable for most of the such cases – Satyajit Feb 08 '16 at 11:57
  • @Satyajit parsing from right to left works in the same number (also different set) of cases than left-to-right: variable length numeric field is on the other end of sequence of digits (like dYYYY - r-l works, YYYYd - l-r works, YYYYdMM you'd have to cut from both sides first). Try to get incoming format changed instead as dealing with date/time is hard already without parsing issues:) – Alexei Levenkov Feb 08 '16 at 17:18
4

Alexei's answer is quite right, I wanna explain little bit deep if you let me..

You are thinking 5 should match with d specifier, right? But this is not how DateTime.ParseExact works under the hood.

Since The "d" custom format specifier represents number from 1 through 31, this specifier will map 52 in your string, not just 5. That's why your code throws FormatException.

As you can see, your string format can't parsed unless you do it some string manipulations with it.

In such a case, .NET Team suggests either using two digit forms like 05 or insert separators for your date and time values.

You can create a custom method that parse this MMMdyyyyhhmmtt format for only parse this kind of formatted strings like;

public static DateTime? ParseDate_MMMdyyyyhhmmtt(string date)
{
    if (date == null)
        return null;
    if (date.Length < 14)
        return null;
    if (date.Length == 14)
        date = date.Insert(3, "0");
    DateTime dt;
    if (DateTime.TryParseExact(date, "MMMdyyyyhhmmtt",
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.None, out dt))
        return dt;
    return null;
}
Community
  • 1
  • 1
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
  • Thanks. You have explained it well in your answer :). I also created my custom method for parsing it later. I was looking for if any direct library method or work around there, instead of custom method. Also, should not c# be taking care of it knowing such case i.e. parse right to left if it fails or something like that. What do you say about it? – Satyajit Feb 08 '16 at 11:49
  • @Satyajit I don't think there will be a library or something for this. You have a bad custom data at first. `DateTime` parsing methods are not perfect to figure out your day `5` or `52` in such a case. For example; what if your `5` will be `1` instead? You will have `1` and `12` which is both valid day numbers. Which one should/would parsed as days? That's quite complicated for any method and for any human. – Soner Gönül Feb 08 '16 at 12:20
  • I realize this is an older question, but thank you for going into more detail about the "under the hood" functionality here. I recently asked a (very) similar question about encountering the same kinds of issues with `TryParseExact()`. As I mentioned in one of my comments, my frustration with this is that, when using the "exact" version of the parser, I'm explicitly telling it that I "*know*" what format the string is in and I want the parser to match that ***exact*** format. If the format specifies a single digit for the day, I would expect it not to try and cram two digits into that field. – G_Hosa_Phat Feb 15 '23 at 15:26
  • @G_Hosa_Phat You are welcome. Sounds like the problem lies in what "exact format" means generally. I think most people confuse about that as "character by character" like `5` matches `d` and `15` matches `dd`. But unfortunately, this is not _how_ implemented. That's why Microsoft [wider form](https://stackoverflow.com/a/26778076/447156) suggestion makes sence. – Soner Gönül Feb 24 '23 at 11:31