1

I have a string (642014) which is in the format Mdyyyy.
I want to convert the string to 04062014(ddMMYYYY).
I have tried the following code.
Please help.

DateTime.TryParseExact("642014", "MMddyyyy",
                       CultureInfo.InvariantCulture,
                       DateTimeStyles.None, out "04062014");
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Borah
  • 21
  • 4
  • 3
    what will be the date for 1112014? – serdar Nov 06 '14 at 07:07
  • Try with `DateTime.TryParseExact("642014", "Mdyyyy", CultureInfo.InvariantCulture);` And remember import `using System.Globalization;` – Benjamin RD Nov 06 '14 at 07:08
  • Perhaps you have confused `Mdyyy` and `MMddyyy`? – Codor Nov 06 '14 at 07:09
  • 3
    in other words how would your format differ 01/11/2014 from 11/01/2014? – serdar Nov 06 '14 at 07:09
  • And looks like you didn't understand how [`out` parameter modifier](http://msdn.microsoft.com/library/en-us/ee332485%28v=vs.100%29.aspx) works. – Soner Gönül Nov 06 '14 at 07:15
  • `out "04062014"` won't work. It's expected that you prepare a variable beforehand, like `DateTime parsedValue;`. Then, if the "try parsing" succeedes, `parsedValue` will contain the value you want. Now you can `ToString` it to any format you want. – Corak Nov 06 '14 at 07:16

3 Answers3

5

That's not a valid date format.

To highlight the issue is 1112014 the 1st of Nov or 11th of Jan?

If you have some sort of convention that allows you to determine which date it refers to in these instances you could do some sort of pre - processing or parse the string manually but you're not going to find anything 'built in' for that format

Stewart_R
  • 13,764
  • 11
  • 60
  • 106
4

Your situation looks like another widest form issue.

From DateTime.TryParseExact method

If you do not use date or time separators in a custom format pattern, 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 pattern, specify the wider form, "HH", instead of the narrower form, "H".

Because of this, parsing strings without any date or time separator might be a problem sometimes.

For example let's talk about "d" custom format specifier. For formatting part, it formats your day part with a single digit without a leading zero. But for parsing, it can parse both 4 and 04 as well. It is the same as "M" custom format specifier. I don't say you should use d specifier for 04. You can, but you shouldn't. You should always use the best formats that fits your string exactly.

Here is my opinion about what is going on here;

Because of the widest form rule, since your string doesn't have any date separator, you format should expect the widest forms of d and M which they are dd and MM. But I think these specifiers expect with a leading zero values (eg: 06 and 04) when they used for single digits because what actually they are for. I couldn't find any evidence to support my theory but I am still investigating it.

I have a solution if your strings have always Mdyyyy format. Maybe it is not the best solution but I think it is useful if your strings have a constant format;

public static DateTime? ParseDate_Mdyyyy(string date)
{
    if (date == null)
        return null;
    if (date.Length < 6)
        return null;
    if (date.Length == 6)
        date = date.Insert(0, "0").Insert(2, "0");
    DateTime dt;
    if (DateTime.TryParseExact(date, "MMddyyyy",
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.None, out dt))
        return dt;
    return null;
}

Now you can use this method as;

string s = "642014";
DateTime? date = ParseDate_Mdyyyy(s);
Console.WriteLine(date.Value.ToString("ddMMyyyy")); // 04062014

I connected to .NET Framework Team about this problem here their response;

Hi Soner,

The parsing code is not really looking for any separator. Here is what is going on:

For the case of using “MMddyyyy”, the parsing starts in the method DoStrictParse which will call ParseByFormat. This method will get the first part of the format which is “MM” and then calls ParseDigits to get the equivalent digits from the string we parse “642014” which will give “64”. Note that till that time there is no validation happen if the number is out of range for the month in the selected calendar (which is Gregorian in our case here). The parsing code will repeat the same process for “dd” and will get equivalent part “20” and then will repeat it for “yyyy” but this fail because it expect 4 digits and we had only two (“14”).

For the case of using “Mdyyyy”, it fails because almost same reason when parsing the part “M” we know that the month can be 2 digits so we’ll map it “64” and will do the same with “d” which map it to “20” and then year will fail. I believe this is the reason the documentation saying always use the widest form.

The recommendation here is either to use the 2 digit forms in the string like "06042014" and the parsing should succeed with “MMddyyyy” and “Mdyyyy” too. other option is to insert separator "6/4/2014" or "06/04/2014" and parse as "M/d/yyyy"

Thanks, Tarek

Special thanks to; Tarek Mahmoud Sayed, Wes Haggard and Richard Lander.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
  • @Downvoter care to comment at least so I can see where I might be wrong? – Soner Gönül Nov 06 '14 at 11:36
  • I'm not the downvoter here but... I think the `1112014` example in the comments and in my answer shows the crux of the OP's problematic format. Your own answer (despite the undoubted value it brings from your knowledge of the `.TryParseExact()` method's aim and implementation) doesn't really address this issue. In this example `date.Length == 7` so it misses all your pre-processing and still arrives at `.TryParseExact()` with the same ambiguity over whether it represents 1st Nov or 11th Jan – Stewart_R Nov 06 '14 at 13:26
  • @Stewart_R Sorry but you are wrong. `1112014` doesn't show OP's problem. You say it will be `1st of Nov` or `11th of Jan`? You are right about `1112014` string but this doesn't effects `642014` string. Why? Because since OP parses this `MMddyyyy` format. We should say ok, `MM` parses `6` and `dd` parses `4` (even they are not for parsing single digits) and `yyyy` parses `2014`. Everything looks right. But it is not. Here we are facing `widest form` rule when string doesn't have a date separator as I mentioned in my answer. – Soner Gönül Nov 06 '14 at 14:58
  • @Stewart_R ...My method is for only parsing string `Mdyyyy` format. It doesn't consider another formats. That's why I said _I have a solution if your strings have always Mdyyyy format_. Using wider specifiers is a rule, but they still expect the values what they are really for. – Soner Gönül Nov 06 '14 at 15:02
-1

To parse your string, first add slash to relevant positions then parse it

string str = "642014";
str = str.Insert(2,"/").Insert(1,"/"); 
var result = DateTime.ParseExact(str, "M/d/yyyy",CultureInfo.InvariantCulture);
asdf_enel_hak
  • 7,474
  • 5
  • 42
  • 84