Date.ParseExact and the subtle goo that is DateTime Format Strings
Sponsored By
We recently needed to parse this evil.
string poop = "2005-12-14T14:35:32.1700000-07:00";
DateTime poo = DateTime.ParseExact(poop,"yyyy-MM-ddTHH:mm:ss.fffffffzzz", System.Globalization.CultureInfo.InvariantCulture);
Important Notes:
- HH means 24 hour time, hh means 12 hour time.
- Don't do all your testing in the morning of a one digit month on a one digit day. 11:59pm on New Years Eve is an important test case.
- If I'd have tested with 01:01:01 then using lower case h's would have worked, but would have broken this afternoon.
- zzz means TimeZone offset like -07:00
- When doing a ParseExact and then round-tripping with a ToString using the same format string will NOT result in the same string.
- That means that:
DateTime foo = DateTime.ParseExact(poo,"yyyy-MM-ddTHH:mm:ss.fffffffzzz", System.Globalization.CultureInfo.InvariantCulture);
foo.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz") == "2005-12-14T13:35:32.1700000-08:00"
However, the semantics of the DateTime is the same. - fffffff means 7 digits of fractional seconds
- T (in this context) has no specific meaning (it’s not reserved) so it is treated as a literal.
- System.Globalization.CultureInfo.InvariantCulture is almost always necessary when you’re working in a non-UI context.
- Don't get screwed when your application doesn't work when installed on an international version of Windows.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
Scott, I just got back from a rare night out with my wife. We decided to wine and dine in opulence, and afterwards enjoy a rich cultural spectacle. So essentially I took her to the happy hour at Stanfords and catch the Amityville Horror. Since when did you have time to take the lead role in a B-rate horror flick? The whole time I was watching the movie it was like some bizarre "TechEd Terror", seeing you struggle against the demons in the house. Seriously, this guy has to be your long-lost brother:
http://movies.go.com/moviesdynamic/movies/movie?name=amityvillhorror_2004&genre=horror&studio=TBA
http://movies.go.com/moviesdynamic/movies/movie?name=amityvillhorror_2004&genre=horror&studio=TBA
Been there :) My NUnit presentations generally show testing date parsing as a no-brainer use of automated testing after thinking about the test cases. As you clearly show it is all too easy to miss a subtlety in ad-hoc testing. In demos I change MM to mm and watch NUnit find the otherwise hard to find defect. HH vs hh is an even better example.
InvariantCulture is a good tip, thanks.
InvariantCulture is a good tip, thanks.
Gerard, valid point. I guess I wasn't too clear in my post.
* This problem needed to be solved (for me) in the context of a ParseExact call. Meaning, the code was generated like:
DateTime.ParseExact(poop,???, System.Globalization.CultureInfo.InvariantCulture)
where the ??? was to come from elsewhere. Since EVERY kind of date format could be passed in, I couldn't make XmlConvert (a very specific kind of translation) the else case.
That said, XmlConvert does work for this one of kind of date string.
Thanks!
* This problem needed to be solved (for me) in the context of a ParseExact call. Meaning, the code was generated like:
DateTime.ParseExact(poop,???, System.Globalization.CultureInfo.InvariantCulture)
where the ??? was to come from elsewhere. Since EVERY kind of date format could be passed in, I couldn't make XmlConvert (a very specific kind of translation) the else case.
That said, XmlConvert does work for this one of kind of date string.
Thanks!
Comments are closed.
Incidentally, this is how our President also solves many problems..