我试图创建一个能够认识到自定义格式字符串为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,所以它只有在没有提供者发现返回DateTimeFormatInfoCultureInfo的一个实例。看来,DateTime.ToString方法不兑现ICustomFormatter界面像StringBuilder.Format方法做,因为你的String.Format例所示。

我同意DateTime.ToString方法应该支持ICustomFormatter接口,但它不似乎目前还。这可能所有已经改变或将在.NET 4.0变化。

其他提示

在短的解释是,当

DateTime.ToString(string format, IFormatProvider provider)

可以传递任何实施IFormatProvider作为它的参数之一,它实际上只支持它的代码2种内可能类型的实施IFormatProvider

DateTimeFormatInfoCultureInfo

如果您的参数不能被(使用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);
        }
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top