如何为 DateTime 创建和使用自定义 IFormatProvider?

发布于 2024-08-24 06:29:59 字数 1396 浏览 7 评论 0原文

我试图创建一个 IFormatProvider 实现来识别 DateTime 对象的自定义格式字符串。这是我的实现:

 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, IFormatProviderprovider) 方法中使用它,如下所示,但是:

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

在该示例中,在美国文化中运行,结果是“00cu0Ao00or0aA”,显然是因为正在解释标准日期时间格式字符串。

但是,当我按以下方式使用同一类时:

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

我得到了我所期望的,即 "Sun Jan 02"

我不明白不同的结果。有人可以解释一下吗?

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蔚蓝源自深海 2024-08-31 06:30:00

使用 Reflector 检查 DateTime.ToString 方法显示 DateTime 结构使用 DateTimeFormatInfo.GetInstance 方法来获取用于格式化的提供程序。 DateTimeFormatInfo.GetInstance 从传入的提供程序请求 DateTimeFormatInfo 类型的格式化程序,从不用于 ICustomFormmater,因此它仅返回 DateTimeFormatInfo 的实例。 code>DateTimeFormatInfo 或 CultureInfo(如果未找到提供者)。似乎 DateTime.ToString 方法不像 StringBuilder.Format 方法那样遵循 ICustomFormatter 接口,正如您的 String.格式示例所示。

我同意 DateTime.ToString 方法应该支持 ICustomFormatter 接口,但目前似乎不支持。在 .NET 4.0 中,这一切可能已经改变或将会改变。

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.

好久不见√ 2024-08-31 06:30:00

使用扩展方法:)

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

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);
        }
    }
余厌 2024-08-31 06:29:59

简而言之,虽然

DateTime.ToString(string format, IFormatProvider provider)

允许您传递任何实现 IFormatProvider 作为其参数之一,但它实际上只支持在其代码中实现 IFormatProvider 的 2 种可能类型:

DateTimeFormatInfo< /code> 或 CultureInfo

如果您的参数无法转换(使用 as)为其中之一,则该方法将默认为 CurrentCulture

String.Format 不受此类限制。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文