如何创建和使用自定义的IFormatProvider为日期时间?
-
24-09-2019 - |
题
我试图创建一个能够认识到自定义格式字符串为datetime对象的IFormatProvider
实现。下面是我实现的:
public class MyDateFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
{
return this;
}
return null;
}
public string Format(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();
}
}
我期待能够使用它在DateTime.ToString(string format, IFormatProvider provider)
方法等左右,但:
DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());
在该示例中,在美国文化运行,其结果是"00cu0Ao00or0aA"
,显然是因为标准DateTime格式字符串被解释
然而,当我使用相同的类以下列方式:
DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);
我得到了我希望,即"Sun Jan 02"
我不理解不同的结果。可能有人解释?
谢谢!
解决方案
检查与所述DateTime.ToString
结构采用DateTime
方法获取提供商反射显示了DateTimeFormatInfo.GetInstance
方法被用于格式化。该DateTimeFormatInfo.GetInstance
请求类型DateTimeFormatInfo
的格式化从供应商传递,从不为ICustomFormmater
,所以它只有在没有提供者发现返回DateTimeFormatInfo
或CultureInfo
的一个实例。看来,DateTime.ToString
方法不兑现ICustomFormatter
界面像StringBuilder.Format
方法做,因为你的String.Format
例所示。
我同意DateTime.ToString
方法应该支持ICustomFormatter
接口,但它不似乎目前还。这可能所有已经改变或将在.NET 4.0变化。
其他提示
在短的解释是,当
DateTime.ToString(string format, IFormatProvider provider)
可以传递任何实施IFormatProvider
作为它的参数之一,它实际上只支持它的代码2种内可能类型的实施IFormatProvider
:
DateTimeFormatInfo
或CultureInfo
如果您的参数不能被(使用as
)作为任一者或那些浇铸,该方法将默认为CurrentCulture
。
String.Format
不受这种界限的限制。
使用扩展方法:)
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);
}
}