【问题标题】:Is String.Format and DateTimeFormatInfo pluggable/extensible?String.Format 和 DateTimeFormatInfo 是可插入/可扩展的吗?
【发布时间】:2010-10-13 10:36:54
【问题描述】:

因此,例如,当我对日期进行 string.format 并在格式模式中使用字符串“或”时,我希望将其转换为日期的序数值。

string.Format("{0:ddor MMM yyyy}.", DateTime.Now)

应该输出

1st Jan 2010

关于如何推导序数,请参见下文

Is there an easy way in .NET to get "st", "nd", "rd" and "th" endings for numbers?

【问题讨论】:

    标签: .net string.format ordinal datetimeformatinfo


    【解决方案1】:

    好像没有类似的东西。

    最推荐的做法:

    var d = DateTime.Now;
    var result2 = String.Format("{0:dd}{1} {2:MMM yyyy}", d, Ordinal(d.Day), d);
    

    实现它的一个非常hacky的方法是创建一个自定义IFormatProvider。 IMO这只是很麻烦,但只是为了展示另一种方式......(我对此没有太多经验,可能不是很“正确”)

    using System;
    
    namespace Test
    {
        class Program
        {
            public static string Ordinal(int number)
            {
                string suffix = String.Empty;
    
                int ones = number % 10;
                int tens = (int)Math.Floor(number / 10M) % 10;
    
                if (tens == 1)
                {
                    suffix = @"\t\h";
                }
                else
                {
                    switch (ones)
                    {
                        case 1:
                            suffix = @"\s\t";
                            break;
    
                        case 2:
                            suffix = @"\n\d";
                            break;
    
                        case 3:
                            suffix = @"\r\d";
                            break;
    
                        default:
                            suffix = @"\t\h";
                            break;
                    }
                }
                return suffix;
            }
    
            public class MyFormat : IFormatProvider, ICustomFormatter
            {
                public object GetFormat(Type formatType)
                {
                    return (formatType == typeof(ICustomFormatter)) ? this : null;
    
                }
    
                public string Format(string format, object arg, IFormatProvider formatProvider)
                {
                    var d = (DateTime)arg;
    
                    var or = Ordinal(d.Day);
    
                    format = format.Replace("or", or);
    
                    return d.ToString(format);
                }
            }
            static void Main(string[] args)
            {
                var result = String.Format(new MyFormat(), "{0:ddor MMM yyyy}.", DateTime.Now);
    
                return;
            }
        }
    }
    

    More info on Custom IFormatProvider

    【讨论】:

    • 感谢布鲁诺的回答。但是我一直在寻找一种对用户没有太大影响的方法。
    【解决方案2】:

    格式提供程序是可插入的,但据我所知,您无法为给定类型设置默认格式提供程序。按照约定采用格式字符串的方法通常还具有采用 IFormatProvider 的重载。您可以实现两个类,例如 MyFormatProvider :IFormatProvider 和 MyCustomFormatter :ICustomFormatter

    当处理“{0:dd}{0:or} {0:MMM} {0:yyyy}”等格式字符串时,您的 ICustomFormatter 将被调用 4 次,分别带有“dd”、“or” ,“MMM”和“yyyy”作为参数,因此它可以分别格式化每个部分。您只需处理“或”的情况,并将其余的传递给默认格式提供程序。

    但是,调用方在格式化时仍需要传入您的自定义格式提供程序的实例。例如:

    string str = String.Format(MyFormatProvider.Default, "{0:dd}{0:or} {0:MMM} {0:yyyy}", date);
    

    据我所知,没有逃避这一要求。不久前,当我创建了一个显示“1 小时前”、“3 天前”等日期时间的“相对”日期时间格式字符串时,我搜索了一种更好的方法。无法找到避免必须明确的方法传递我的自定义 IFormatProvider。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多