How to create and use a custom IFormatProvider for DateTime?

倾然丶 夕夏残阳落幕 提交于 2019-11-26 20:35:47

问题


I was trying to create an IFormatProvider implementation that would recognize custom format strings for DateTime objects. Here is my implementation:

 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();
   }
  } 

I was expecting to be able to use it in the DateTime.ToString(string format, IFormatProvider provider) method like so, but :

DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());

In that example, running in the US Culture, the result is "00cu0Ao00or0aA", apparently because the standard DateTime format strings are being interpreted.

However, when I use the same class in the following way:

DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);

I get what I expect, namely "Sun Jan 02"

I don't understand the different results. Could someone explain?

Thanks!


回答1:


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.




回答2:


The short explanation is that while

DateTime.ToString(string format, IFormatProvider provider)

lets you pass anything implementing IFormatProvider as one of it's parameters, it actually only supports 2 possible types implementing IFormatProvider inside it's 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.




回答3:


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);
        }
    }


来源:https://stackoverflow.com/questions/2382154/how-to-create-and-use-a-custom-iformatprovider-for-datetime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!