tags:

views:

85

answers:

3

This is very weird. I have the following code:

Assert.AreEqual(new DateTime(2000, 1, 1), DateTime.ParseExact("2000", "yyyy", CultureInfo.InvariantCulture));
Assert.AreEqual(new DateTime(2000, 1, 1), DateTime.ParseExact("20000705", "yyyy", CultureInfo.InvariantCulture));

The first line passes, the second one fails with "System.FormatException: String was not recognized as a valid DateTime".

I cannot shorten the string to be parsed to match the length of the format - it would work in this particular case, but this is part of a more generic method, and it would fail somewhere else. Any idea on why the second call fails?

[Edit] Ok, I was hoping it was parsing just as much of the input string as needed to satisfy the format.

I get a lot of strings in a lot of formats, and I have one method that accepts both and, after a bit of processing (I only get dates, so I replace "m" with "M" and "Y" with "y" and so on), I call DateTime.ParseExact. The reason I cannot call DateTime.Parse is because it doesn't allow for a format argument... I can get ddMMyyyy in one part of the program and yyyyddMM in another, there's no way for it to correctly figure it out.

[Edit 2] I guess it's my fault... I'll have to truncate the input when that issue arises. Fortunately I generally have all parts of the date in the format, this (just the year) is a rare occurence. Thanks for the help.

+2  A: 

It's absolutely right to fail - you've told it to expect exactly 4 characters, and then given it 8!

Options:

  • Provide more format strings (e.g. "yyyyMMdd") to the call (you can specify multiple valid formats)
  • Only pass in the piece of the string you expect to match the format
  • Parse the string yourself

You claim that truncating the string "would fail somewhere else" - could you give more details? If you're specifying "yyyy" then presumably you know you need exactly 4 characters... do you know exactly where they'll be within the string? If so, why can't you perform the truncation?

Jon Skeet
A: 

The highest date that the DateTime can represent is December 31st 9999. You're asking it to understand a year greater than 9999. You either need to specify a format matching the value you're giving it, so that it understands that just the first 4 digits is the year. "yyyymmdd", for example.

Patrick Karcher
+1  A: 

It failed because DateTime.ParseExact requires the input string to match the specified format exactly (err, I mean almost exactly, per your comment below), and "20000705" does not match "yyyy".

To parse "20000705", you'll need to use a different technique - either ParseExact with an appropriate format string (like "yyyyMMdd"), or DateTime.Parse, which is a bit more forgiving (though also less accurate).

It looks like you're trying to extract the year from the date string - no parse method will do that for you.

Instead you should get the actual DateTime represented by the string - July 5th 2000 or May 7th 2000, depending on your format - and then extract the year using DateTime.Year.

Jeff Sternal
I understand the point of the name, but it's not entirely accurate, as this works: Assert.AreEqual(new DateTime(2000, 7, 5), "07/05/2000".ParseDate("M/d/yyyy"));(Where ParseDate ultimately calls DateTime.ParseExact.)It works even though the input string has two digits per month and day, and the format only specifies one. Incidentally, this is the reason I can't cut the input string to match the length of the format string.
Marcel Popescu
How strange. Maybe it's because it's also an output specifier and the designers thought it should be more tolerant when parsing input. The documentation (http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx#M_Specifier) could certainly be clearer.
Jeff Sternal