What does IFormatProvider do?
In adition to Ian Boyd's answer:
Also CultureInfo
implements this interface and can be used in your case. So you could parse a French date string for example; you could use
var ci = new CultureInfo("fr-FR");
DateTime dt = DateTime.ParseExact(yourDateInputString, yourFormatString, ci);
The IFormatProvider
interface is normally implemented for you by a CultureInfo
class, e.g.:
CultureInfo.CurrentCulture
CultureInfo.CurrentUICulture
CultureInfo.InvariantCulture
CultureInfo.CreateSpecificCulture("de-CA") //German (Canada)
The interface is a gateway for a function to get a set of culture-specific data from a culture. The two commonly available culture objects that an IFormatProvider
can be queried for are:
DateTimeFormatInfo
:IFormatProvider.GetFormat(typeof(DateTimeFormatInfo));
NumberFormatInfo
:IFormatProvider.GetFormat(typeof(NumberFormatInfo));
The way it would normally work is you ask the IFormatProvider
to give you a DateTimeFormatInfo
object:
DateTimeFormatInfo? format;
format = (DateTimeFormatInfo)provider.GetFormat(typeof(DateTimeFormatInfo));
if (format != null)
DoStuffWithDatesOrTimes(format);
There's also inside knowledge that any IFormatProvider
interface is likely being implemented by a class that descends from CultureInfo
, or descends from DateTimeFormatInfo
, so you could cast the interface directly:
CultureInfo? info = provider as CultureInfo;
if (info != null)
format = info.DateTimeInfo;
else
{
DateTimeFormatInfo? dtfi = provider as DateTimeFormatInfo;
if (dtfi != null)
format = dtfi;
else
format = (DateTimeFormatInfo)provider.GetFormat(typeof(DateTimeFormatInfo));
}
if (format != null)
DoStuffWithDatesOrTimes(format);
But don't do that
All that hard work has already been written for you:
To get a DateTimeFormatInfo
from an IFormatProvider
:
DateTimeFormatInfo format = DateTimeFormatInfo.GetInstance(provider);
To get a NumberFormatInfo
from an IFormatProvider
:
NumberFormatInfo format = NumberFormatInfo.GetInstance(provider);
The virtue of IFormatProvider
is that you create your own culture objects. As long as they implement IFormatProvider
, and return objects they're asked for, you can bypass the built-in cultures.
You can also use IFormatProvider
for a way of passing arbitrary culture objects - through the IFormatProvider
. E.g. the name of god in different cultures
- god
- God
- Jehova
- Yahwe
- יהוה
- אהיה אשר אהיה
This lets your custom LordsNameFormatInfo
class ride along inside an IFormatProvider
, and you can preserve the idiom.
In reality you will never need to call GetFormat
method of IFormatProvider
yourself.
Whenever you need an IFormatProvider
you can pass a CultureInfo
object:
DateTime.Now.ToString(CultureInfo.CurrentCulture);
endTime.ToString(CultureInfo.InvariantCulture);
transactionID.toString(CultureInfo.CreateSpecificCulture("qps-ploc"));
Note: Any code is released into the public domain. No attribution required.
Passing null as the IFormatProvider
is not the correct way to do this. If the user has a custom date/time format on their PC you'll have issues in parsing and converting to string. I've just fixed a bug where somebody had passed null as the IFormatProvider when converting to string.
Instead you should be using CultureInfo.InvariantCulture
Wrong:
string output = theDate.ToString("dd/MM/yy HH:mm:ss.fff", null);
Correct:
string output = theDate.ToString("dd/MM/yy HH:mm:ss.fff", CultureInfo.InvariantCulture);