Scott Hanselman

Don't underestimate the power of ToString(IFormatProvider)

January 19, 2005 Comment on this post [5] Posted in Internationalization | Bugs | Tools
Sponsored By

UPDATE: I write this update minus one pinky finger. In the comments RichB and Paul van Brenk pointed out two bugs in my solution. First, RichB points out that ':' is a format modifier itself that describes the hours separator . So, that needs to be escaped. It can be escape either like \: or ':'. Paul points out that the final call to ToString should use the InvariantCulture, lest I end up with odd characters. Since I used the double (MM) numeric formats, this isn't a problem in 99% of cultures, but I could change calendars inadvertantly in Thai, in the Maldives, or in Saudi Arabia where different calendars are used.

Do NOT underestimate the power of ToString(IFormatProvider). I caught a fellow trying to to a DateTime conversion recently. He had do a (culture senstive) DateTime.ToString() then started parsing it into the specific format he wanted.

This is the height of pure evil and anyone who does it should lose a pinky. It's harder to parse these strings minus a little finger, and while harsh, this kind of punishment should deter others from making the same mistake.

The original question:

I have a DateTime variable which is holding the value as “1/13/2005 1:29:54 PM” and I want to convert to “20050113132954.000[0:GMT]”.

An answer:

DateTime foo = new DateTime(2005,1,13,13,29,54);
//TOTALLY OPTIONAL, but worth noting, assuming it was local time
DateTime bar = foo.ToUniversalTime();
string myNewDate = bar.ToString(@"yyyyMMddHHmmss.000[0\:G\MT]",System.Globalization.CultureInfo.InvariantCulture);

Notice the escaping on the "M" in the string literal "GMT." That's because "M" by itself is a Month formatter, so we say "no seriously, I meant M" by using "\M". Also, remember that "HH" is "zero-prepended 24-hour time" while "H" is "no-zeros 24-hour time" and "hh" and "h" are 12-hour times respectively. There are similar rules with "MM" for months and "mm" for minutes.

The final tip, don't even bother trying to do this stuff from memory without Chris Sells' FormatDesigner.

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
January 19, 2005 11:22
Be careful about cutting off other people's fingers - you may trip yourself up and have to cut off your own! The ':' in that string is a special character which means "Replace the ':' with the time separater character defined for the current culture".

So, ToString(IFormatProvider) _is_ powerful, but it is so "powerful" it can even hurt experts.

(The answer is to enclose the colon in single quotes)
January 19, 2005 16:52
You may want to throw in an CultureInfo.InvariantCulture to make sure the date isn't parsed as chinese or Hindi.
January 19, 2005 21:09
Rich - good stuff. So there are TWO ways to escape? Single quotes AND backslashes?
January 19, 2005 21:10
Paul, good point. Details, always the details. I'll update the post.
January 20, 2005 0:09
An extra note about requiring the InvariantCulture - not all calendars are Gregorian (as you pointed out). You could have the Japanese imperial calendar if your code was used in Japan - however, the Windows user would have to deliberately change their calendar away from Gregorian for this to have effect. However - there are locales like the Maldives which do not use the Gregorian calendar by default and instead use the Hijri calendar by default on Windows systems.

Perhaps we should be fortunate that Windows doesn't support the French Revolutionary calendar.

Comments are closed.

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