Framework tips III: DateTime.ToString() explained

There seems to be much confusion around how DateTime’s ToString method actually works. Let me try to clear it out for you:

First, there are several ways of converting DateTime to String:

   1: public String ToLongDateString() {...}

   2: public String ToLongTimeString() {...}

   3: public String ToShortDateString() {...}

   4: public String ToShortTimeString() {...}

   5: public override String ToString() {...}

   6: public String ToString(String format) {...}

   7: public String ToString(IFormatProvider provider) {...}

   8: public String ToString(String format, IFormatProvider provider) {...}

Every of this methods calls internal method giving it reference to itself, format string and DateTimeFormatInfo instance.

Calling methods 1 – 7 is like calling method 8, with given parameters:

Method (and its parameters)

8th method’s parameters

ToLongDateString() (“D”, DateTimeFormatInfo.CurrentInfo)
ToLongTimeString() (“T”, DateTimeFormatInfo.CurrentInfo)
ToShortDateString() (“d”, DateTimeFormatInfo.CurrentInfo)
ToShortTimeString() (“t”, DateTimeFormatInfo.CurrentInfo)
ToString() (null, DateTimeFormatInfo.CurrentInfo)
ToString(String format) (format, DateTimeFormatInfo.CurrentInfo)
ToString(IFormatProvider provider) (null, DateTimeFormatInfo.GetInstance(provider))

If you don’t specify IFormatProvider, DateTimeFormatInfo.CurrentInfo is used, that is basically:

   1: System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat;

So although you may be very specific about your format, Current culture will be still take into account, which may result in unexpected strings in some cultures. Notice that there are basically three kinds of format you may provide:

  1. null (or string.Empty)
  2. one-character long predefined format
  3. multi-character long custom format

If you provide null (or empty string), in almost every occasion this will result in General date/long time formatting (same as providing “G” as format).

There is a list of all predefined formats here. Notice however that for ‘o’, “O”, “r”, “R”, “s” and “u”, invariant DateTimeFormatInfo, will always be used. Next, predefined format will be expanded according to given DateTimeFormatInfo’ properties (or their combinations), and ultimately, in all three above cases will end up with fully expanded formatting string, that will get translated to date-time string according to rules specified in second table on this site.

Notice however that ‘:’ and ‘/’ have special meaning and are not treated like literals. If you do need to use them (or any other formatting character) as literal, you have to precede it with ‘\’. If you want to embed longer literal string in the format you have to put it within ” or ‘ characters.


.NET Framework does its best to display date and time according to user’s settings, but if you need to make sure that date and time will always be displayed the same way despite of user’s settings, use the last overload, and pass some DateTimeFormatInfo instace. Otherwise, even if you use specific format strings like “yyyy-MM-dd HH:mm”, you may end up with strings like: תשס”ח-ה’-י”א 10:06

Technorati Tags: , , ,