Scott Hanselman

Date.ParseExact and the subtle goo that is DateTime Format Strings

April 15, 2005 Comment on this post [5] Posted in Internationalization
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.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
April 16, 2005 5:19
I solve this problem by imagining a world with only one culture.

Incidentally, this is how our President also solves many problems..
April 16, 2005 9:45
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
April 24, 2005 0:19
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.
April 25, 2005 21:58
Why not:

DateTime foo = XmlConvert.ToDateTime(poop);
April 25, 2005 22:03
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!

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.