How to create and use a custom IFormatProvider for DateTime?
The short explanation is that while
DateTime.ToString(string format, IFormatProvider provider)
lets you pass anything implementing IFormatProvider
as one of its parameters, it actually only supports 2 possible types implementing IFormatProvider
inside its code:
DateTimeFormatInfo
or CultureInfo
If your parameter cannot be casted (using as
) as either or those, the method will default to CurrentCulture
.
String.Format
is not limited by such bounds.
Checking the DateTime.ToString
method with Reflector shows that the DateTime
structure uses the DateTimeFormatInfo.GetInstance
method to get the provider to be used for formatting. The DateTimeFormatInfo.GetInstance
requests a formatter of type DateTimeFormatInfo
from the provider passed in, never for ICustomFormmater
, so it only returns an instance of a DateTimeFormatInfo
or CultureInfo
if no provider is found. It seems that the DateTime.ToString
method does not honor the ICustomFormatter
interface like the StringBuilder.Format
method does, as your String.Format
example shows.
I agree that the DateTime.ToString
method should support the ICustomFormatter
interface, but it does not seem to currently. This may all have changed or will change in .NET 4.0.
Use extension method :)
public static class FormatProviderExtension
{
public static string FormatIt(string format, object arg, IFormatProvider formatProvider)
{
if (arg == null) throw new ArgumentNullException("arg");
if (arg.GetType() != typeof(DateTime)) return arg.ToString();
DateTime date = (DateTime)arg;
switch (format)
{
case "mycustomformat":
switch (CultureInfo.CurrentCulture.Name)
{
case "en-GB":
return date.ToString("ddd dd MMM");
default:
return date.ToString("ddd MMM dd");
}
default:
throw new FormatException();
}
}
public static string ToString(this DateTime d, IFormatProvider formatProvider, string format)
{
return FormatIt(format, d, formatProvider);
}
}