【问题标题】:Formatting string dates with String.Format()使用 String.Format() 格式化字符串日期
【发布时间】:2012-07-26 06:47:10
【问题描述】:

只是好奇... 所以我知道,如果我将日期的字符串版本转换为 DateTime 对象并将其传递给 String.Format() 方法,那么我将得到所需的结果。

String.Format("The date is {0:MMMM dd, yyyy}", DateTime.Parse("05-22-2012"));

“日期是 2012 年 5 月 22 日”

但是为什么这不起作用呢?

String.Format("The date is {0:MMMM dd, yyyy}", "05-22-2012")

"日期是 05-22-2012"

对不起,如果这是一个愚蠢的问题,但我只是想了解它是如何工作的。 谢谢

【问题讨论】:

    标签: c# string datetime


    【解决方案1】:

    这里的其他答案很重要,但让我们把它们放在一起,看看String.Format 是如何工作的。

    它有五个重载,但我们只讨论它们都重定向到的那个(这不是实际代码,如果你想用 Reflector 或 ILSpy 看到它,你可以在 @987654322 中找到它@)。这是为了便于理解而进行了简化。

    public static string Format(IFormatProvider provider, string format, params object[] args)
    {
        StringBuilder sb = new StringBuilder();
    
        // Break up the format string into an array of tokens
        Token[] tokens = ParseFormatString(format);
    
        foreach (Token token in tokens)
        {
            switch (token.TokenType)
            {
                // A Text token is just some text to output directly
                case TokenType.Text:
                    sb.Append(token.Text);
                    break;
    
                // An Index token represents something like {0} or {2:format}
                //  token.Index is the argument index
                //  token.FormatText is the format string inside ('' in the first example, 'format' in the second example)
                case TokenType.Index:
                    {
                        object arg = args[token.Index];
    
                        IFormattable formattable = arg as IFormattable;
                        if (formattable != null && token.FormatText.Length > 0)
                        {
                            // If the argument is IFormattable we pass it the format string specified with the index
                            sb.Append(formattable.ToString(token.FormatText, provider));
                        }
                        else
                        {
                            // Otherwise we just use Object.ToString
                            sb.Append(arg.ToString());
                        }
                    }
                    break;
            }
        }
    
        return sb.ToString();
    }
    

    在您的问题中,您问为什么当您传递“05-22-2012”时格式字符串不被应用。正如 Guffa 所说,那不是 DateTime 对象,而是 String 对象。

    正如 GSerjo 所说,String 不是 IFormattable。字符串不可格式化,因为格式化是将某些内容转换为字符串的过程。字符串已经是字符串了!

    因此您可以看到,当 Format 方法到达索引器时,arg 不会是 IFormattable,它只会调用 ToString。对字符串调用 ToString 只会返回自身,它已经是一个字符串。

    总而言之,如果您的格式字符串包含带有内部格式字符串的索引(例如 {0:format}),则仅当关联参数为 IFormattable 并且它知道要做什么时,才会应用该内部格式字符串用你给它的格式字符串做。

    【讨论】:

    • 这真的为我带来了它,很好的解释。谢谢!
    【解决方案2】:

    自定义日期时间格式仅适用于 DateTime 值。如果您改用字符串,格式将被忽略,因为只有一种方法可以输出字符串。

    【讨论】:

      【解决方案3】:

      因为“05-22-2012”不是IFormattableDateTime.Parse("05-22-2012")DateTime

      请在此处查看更多示例

      【讨论】:

      • 谢谢,我可以更好地掌握接口是如何实现的。我理解他们,但显然忽略了他们。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多