In the last post, Adding Ordinal Support To DateTime Format Strings In C# & .NET we looked at how to implement robust support for ordinal format strings.

This allows us to write code like this:

var date = DateTime.Now.AddDays(-2);
Console.WriteLine(string.Format(new OrdinalDateFormatProvider(), "{0:do MMM}", date));
Console.WriteLine(string.Format(new OrdinalDateFormatProvider(), "{0:MMM do MMM}", date));

This will print the following:

20th Aug
Aug 20th Aug

I, however, noticed something curious when I attempted to use the ToString() method of the DateTime. Indeed, there is an overload supporting passing of an IFormatProvider.

Console.WriteLine(date.ToString("do MMM yyyy", new OrdinalDateFormatProvider()));

This prints the following:

20o Aug 2025

You can see here that the ordinal format string , o, is ignored.

I found this curious because, on paper, it should work.

It turns out that how ToString() and String.Format() work is different.

String.Format() directly delegates the formatting to the specified provider. It is up to the provider to either handle it or delegate it further..

ToString(), however, works the other way. It will only use the custom provider if none of the components of the format string are recognized by the default provider.

In this case, it recognizes MMM as a valid string and decides to use it instead.

TLDR

To have maximum flexibility, use String.Format to be in full control of how your data is formatted.

Happy hacking!