如何使用 ToString() 格式化可为空的 DateTime?

Posted

技术标签:

【中文标题】如何使用 ToString() 格式化可为空的 DateTime?【英文标题】:How can I format a nullable DateTime with ToString()? 【发布时间】: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 方法没有重载 一个论点

【问题讨论】:

您好,您介意查看已接受和当前的答案吗?一个更相关的今天的答案可能更正确。 【参考方案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 并不是说​​任务不简单...***.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() 然后进行复杂的格式化。 ***.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)

【讨论】:

以上是关于如何使用 ToString() 格式化可为空的 DateTime?的主要内容,如果未能解决你的问题,请参考以下文章

如何在基于块的 API 方法中使用非空和可为空的 Objective-C 关键字

如何使用 Java 互操作处理可为空的泛型

如何使用 System.Text.Json 处理可为空的引用类型?

如何绑定可为空的十进制值

如何将 int.TryParse 与可为空的 int 一起使用? [复制]

如何在 VB.NET 中将可为空的 DateTime 设置为空?