【问题标题】:How can I format a nullable DateTime with ToString()?如何使用 ToString() 格式化可为空的 DateTime?
【发布时间】:2010-12-22 10:16:23
【问题描述】:

如何将可为空的 DateTime dt2 转换为格式化字符串?

DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToString("yyyy-MM-dd hh:mm:ss")); //works

DateTime? dt2 = DateTime.Now;
Console.WriteLine(dt2.ToString("yyyy-MM-dd hh:mm:ss")); //gives following error:

ToString 方法没有重载 一个论点

【问题讨论】:

  • 您好,您介意查看已接受和当前的答案吗?一个更相关的今天的答案可能更正确。

标签: c# datetime formatting nullable


【解决方案1】:
Console.WriteLine(dt2 != null ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "n/a"); 

编辑:如其他 cmets 所述,检查是否存在非空值。

更新:在cmets中推荐,扩展方法:

public static string ToString(this DateTime? dt, string format)
    => dt == null ? "n/a" : ((DateTime)dt).ToString(format);

从 C# 6 开始,您可以使用 null-conditional operator 进一步简化代码。如果DateTime? 为null,则下面的表达式将返回null。

dt2?.ToString("yyyy-MM-dd hh:mm:ss")

【讨论】:

  • 这看起来像是在乞求我的扩展方法。
  • @David 并不是说​​任务不简单...stackoverflow.com/a/44683673/5043056
  • 你准备好了吗... dt?.ToString("dd/MMM/yyyy") ?? "" C#6 的巨大优势
  • 错误 CS0029:无法将类型“字符串”隐式转换为“System.DateTime?” (CS0029)。 .Net Core 2.0
  • 为什么要强制转换为不可空而不是只使用dt.Value
【解决方案2】:

您可以使用dt2.Value.ToString("format"),但当然这需要 dt2 != null,这首先否定了可空类型的使用。

这里有几种解决方案,但最大的问题是:你想如何格式化null 日期?

【讨论】:

    【解决方案3】:

    试穿一下尺寸:

    您要格式化的实际 dateTime 对象位于 dt.Value 属性中,而不是 dt2 对象本身。

    DateTime? dt2 = DateTime.Now;
     Console.WriteLine(dt2.HasValue ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "[N/A]");
    

    【讨论】:

      【解决方案4】:

      制定此问题的答案的问题在于,当可空日期时间没有值时,您没有指定所需的输出。下面的代码在这种情况下会输出DateTime.MinValue,与目前接受的答案不同,不会抛出异常。

      dt2.GetValueOrDefault().ToString(format);
      

      【讨论】:

        【解决方案5】:

        我认为您必须使用 GetValueOrDefault-Methode。如果实例为空,则未定义 ToString("yy...") 的行为。

        dt2.GetValueOrDefault().ToString("yyy...");
        

        【讨论】:

        • 如果实例为空,则定义 ToString("yy...") is 的行为,因为 GetValueOrDefault() 将返回 DateTime.MinValue
        【解决方案6】:

        正如其他人所说,您需要在调用 ToString 之前检查 null 但为避免重复自己,您可以创建一个扩展方法来执行此操作,例如:

        public static class DateTimeExtensions {
        
          public static string ToStringOrDefault(this DateTime? source, string format, string defaultValue) {
            if (source != null) {
              return source.Value.ToString(format);
            }
            else {
              return String.IsNullOrEmpty(defaultValue) ?  String.Empty : defaultValue;
            }
          }
        
          public static string ToStringOrDefault(this DateTime? source, string format) {
               return ToStringOrDefault(source, format, null);
          }
        
        }
        

        可以这样调用:

        DateTime? dt = DateTime.Now;
        dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss");  
        dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss", "n/a");
        dt = null;
        dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss", "n/a")  //outputs 'n/a'
        

        【讨论】:

          【解决方案7】:

          这是一种更通用的方法。这将允许您对任何可为空的值类型进行字符串格式化。我已经包含了第二种方法来允许覆盖默认字符串值,而不是使用值类型的默认值。

          public static class ExtensionMethods
          {
              public static string ToString<T>(this Nullable<T> nullable, string format) where T : struct
              {
                  return String.Format("{0:" + format + "}", nullable.GetValueOrDefault());
              }
          
              public static string ToString<T>(this Nullable<T> nullable, string format, string defaultValue) where T : struct
              {
                  if (nullable.HasValue) {
                      return String.Format("{0:" + format + "}", nullable.Value);
                  }
          
                  return defaultValue;
              }
          }
          

          【讨论】:

            【解决方案8】:

            看到您实际上想要提供格式,我建议您将 IFormattable 接口添加到 Smalls 扩展方法中,这样您就没有讨厌的字符串格式连接。

            public static string ToString<T>(this T? variable, string format, string nullValue = null)
            where T: struct, IFormattable
            {
              return (variable.HasValue) 
                     ? variable.Value.ToString(format, null) 
                     : nullValue;          //variable was null so return this value instead   
            }
            

            【讨论】:

              【解决方案9】:

              IFormattable 还包括一个可以使用的格式提供程序,它允许 IFormatProvider 的两种格式在 dotnet 4.0 中都为空,这将是

              /// <summary>
              /// Extentionclass for a nullable structs
              /// </summary>
              public static class NullableStructExtensions {
              
                  /// <summary>
                  /// Formats a nullable struct
                  /// </summary>
                  /// <param name="source"></param>
                  /// <param name="format">The format string 
                  /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
                  /// <param name="provider">The format provider 
                  /// If <c>null</c> the default provider is used</param>
                  /// <param name="defaultValue">The string to show when the source is <c>null</c>. 
                  /// If <c>null</c> an empty string is returned</param>
                  /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
                  public static string ToString<T>(this T? source, string format = null, 
                                                   IFormatProvider provider = null, 
                                                   string defaultValue = null) 
                                                   where T : struct, IFormattable {
                      return source.HasValue
                                 ? source.Value.ToString(format, provider)
                                 : (String.IsNullOrEmpty(defaultValue) ? String.Empty : defaultValue);
                  }
              }
              

              与命名参数一起使用你可以做到:

              dt2.ToString(defaultValue: "n/a");

              在旧版本的 dotnet 中,您会遇到很多重载

              /// <summary>
              /// Extentionclass for a nullable structs
              /// </summary>
              public static class NullableStructExtensions {
              
                  /// <summary>
                  /// Formats a nullable struct
                  /// </summary>
                  /// <param name="source"></param>
                  /// <param name="format">The format string 
                  /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
                  /// <param name="provider">The format provider 
                  /// If <c>null</c> the default provider is used</param>
                  /// <param name="defaultValue">The string to show when the source is <c>null</c>. 
                  /// If <c>null</c> an empty string is returned</param>
                  /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
                  public static string ToString<T>(this T? source, string format, 
                                                   IFormatProvider provider, string defaultValue) 
                                                   where T : struct, IFormattable {
                      return source.HasValue
                                 ? source.Value.ToString(format, provider)
                                 : (String.IsNullOrEmpty(defaultValue) ? String.Empty : defaultValue);
                  }
              
                  /// <summary>
                  /// Formats a nullable struct
                  /// </summary>
                  /// <param name="source"></param>
                  /// <param name="format">The format string 
                  /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
                  /// <param name="defaultValue">The string to show when the source is null. If <c>null</c> an empty string is returned</param>
                  /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
                  public static string ToString<T>(this T? source, string format, string defaultValue) 
                                                   where T : struct, IFormattable {
                      return ToString(source, format, null, defaultValue);
                  }
              
                  /// <summary>
                  /// Formats a nullable struct
                  /// </summary>
                  /// <param name="source"></param>
                  /// <param name="format">The format string 
                  /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
                  /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
                  /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
                  public static string ToString<T>(this T? source, string format, IFormatProvider provider)
                                                   where T : struct, IFormattable {
                      return ToString(source, format, provider, null);
                  }
              
                  /// <summary>
                  /// Formats a nullable struct or returns an empty string
                  /// </summary>
                  /// <param name="source"></param>
                  /// <param name="format">The format string 
                  /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
                  /// <returns>The formatted string or an empty string if the source is null</returns>
                  public static string ToString<T>(this T? source, string format)
                                                   where T : struct, IFormattable {
                      return ToString(source, format, null, null);
                  }
              
                  /// <summary>
                  /// Formats a nullable struct
                  /// </summary>
                  /// <param name="source"></param>
                  /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
                  /// <param name="defaultValue">The string to show when the source is <c>null</c>. If <c>null</c> an empty string is returned</param>
                  /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
                  public static string ToString<T>(this T? source, IFormatProvider provider, string defaultValue)
                                                   where T : struct, IFormattable {
                      return ToString(source, null, provider, defaultValue);
                  }
              
                  /// <summary>
                  /// Formats a nullable struct or returns an empty string
                  /// </summary>
                  /// <param name="source"></param>
                  /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
                  /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
                  public static string ToString<T>(this T? source, IFormatProvider provider)
                                                   where T : struct, IFormattable {
                      return ToString(source, null, provider, null);
                  }
              
                  /// <summary>
                  /// Formats a nullable struct or returns an empty string
                  /// </summary>
                  /// <param name="source"></param>
                  /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
                  public static string ToString<T>(this T? source) 
                                                   where T : struct, IFormattable {
                      return ToString(source, null, null, null);
                  }
              }
              

              【讨论】:

                【解决方案10】:

                你们对这一切都进行了过度设计,并使其变得比实际情况更复杂。重要的是,停止使用 ToString 并开始使用像 string.Format 这样的字符串格式或支持像 Console.WriteLine 这样的字符串格式的方法。这是此问题的首选解决方案。这也是最安全的。

                更新:

                我使用当今 C# 编译器的最新方法更新示例。 conditional operators & string interpolation

                DateTime? dt1 = DateTime.Now;
                DateTime? dt2 = null;
                
                Console.WriteLine("'{0:yyyy-MM-dd hh:mm:ss}'", dt1);
                Console.WriteLine("'{0:yyyy-MM-dd hh:mm:ss}'", dt2);
                // New C# 6 conditional operators (makes using .ToString safer if you must use it)
                // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators
                Console.WriteLine(dt1?.ToString("yyyy-MM-dd hh:mm:ss"));
                Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss"));
                // New C# 6 string interpolation
                // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated
                Console.WriteLine($"'{dt1:yyyy-MM-dd hh:mm:ss}'");
                Console.WriteLine($"'{dt2:yyyy-MM-dd hh:mm:ss}'");
                

                输出:(我在里面放了单引号,这样你就可以看到它在 null 时以空字符串的形式返回)

                '2019-04-09 08:01:39'
                ''
                2019-04-09 08:01:39
                
                '2019-04-09 08:01:39'
                ''
                

                【讨论】:

                • 第二个选项是更好的选择。 String.Format() 无论如何都必须调用 .ToString() 然后进行复杂的格式化。 stackoverflow.com/questions/10400142/string-format-vs-tostring
                • @ChristenDen 并非总是如此。这仅在最近的 C# 更新中引入。而且...大多数时候,当您为显示/记录目的格式化字符串时,您会使用多个参数来构建字符串。
                【解决方案11】:

                简单的通用扩展

                public static class Extensions
                {
                
                    /// <summary>
                    /// Generic method for format nullable values
                    /// </summary>
                    /// <returns>Formated value or defaultValue</returns>
                    public static string ToString<T>(this Nullable<T> nullable, string format, string defaultValue = null) where T : struct
                    {
                        if (nullable.HasValue)
                        {
                            return String.Format("{0:" + format + "}", nullable.Value);
                        }
                
                        return defaultValue;
                    }
                }
                

                【讨论】:

                  【解决方案12】:

                  C# 6.0 宝贝:

                  dt2?.ToString("dd/MM/yyyy");

                  【讨论】:

                  • 我建议使用以下版本,以便此答案等同于 C# 6.0 的现有公认答案。 Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
                  【解决方案13】:

                  也许这是一个迟到的答案,但可能对其他人有所帮助。

                  简单的是:

                  nullabledatevariable.Value.Date.ToString("d")
                  

                  或者只使用任何格式而不是“d”。

                  最好的

                  【讨论】:

                  • 当 nullabledatevariable.Value 为 null 时会出错。
                  【解决方案14】:

                  你可以用简单的线:

                  dt2.ToString("d MMM yyyy") ?? ""
                  

                  【讨论】:

                    【解决方案15】:

                    我喜欢这个选项:

                    Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss") ?? "n/a");
                    

                    【讨论】:

                      【解决方案16】:

                      像这样简单的事情怎么样:

                      String.Format("{0:dd/MM/yyyy}", d2)
                      

                      【讨论】:

                        【解决方案17】:

                        这里是Blake's excellent answer 作为扩展方法。将此添加到您的项目中,问题中的调用将按预期工作。
                        这意味着它与MyNullableDateTime.ToString("dd/MM/yyyy") 一样使用,输出与MyDateTime.ToString("dd/MM/yyyy") 相同,但如果DateTime 为null,则该值将为"N/A"

                        public static string ToString(this DateTime? date, string format)
                        {
                            return date != null ? date.Value.ToString(format) : "N/A";
                        }
                        

                        【讨论】:

                          【解决方案18】:

                          最短答案

                          $"{dt:yyyy-MM-dd hh:mm:ss}"
                          

                          测试

                          DateTime dt1 = DateTime.Now;
                          Console.Write("Test 1: ");
                          Console.WriteLine($"{dt1:yyyy-MM-dd hh:mm:ss}"); //works
                          
                          DateTime? dt2 = DateTime.Now;
                          Console.Write("Test 2: ");
                          Console.WriteLine($"{dt2:yyyy-MM-dd hh:mm:ss}"); //Works
                          
                          DateTime? dt3 = null;
                          Console.Write("Test 3: ");
                          Console.WriteLine($"{dt3:yyyy-MM-dd hh:mm:ss}"); //Works - Returns empty string
                          
                          Output
                          Test 1: 2017-08-03 12:38:57
                          Test 2: 2017-08-03 12:38:57
                          Test 3: 
                          

                          【讨论】:

                            【解决方案19】:

                            在 C# 6.0 中甚至是更好的解决方案:

                            DateTime? birthdate;
                            
                            birthdate?.ToString("dd/MM/yyyy");
                            

                            【讨论】:

                              【解决方案20】:

                              RAZOR 语法:

                              @(myNullableDateTime?.ToString("yyyy-MM-dd") ?? String.Empty)
                              

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 2013-08-26
                                • 2014-09-30
                                • 1970-01-01
                                • 2021-12-19
                                • 1970-01-01
                                相关资源
                                最近更新 更多